Day3.数组-切片-时间-日期

一.数组

(一).基本属性

1. var 变量名 [len]type
2. var a [5]int
3. 访问数组元素a[0],a[1]...下标从0开始。
4. 数组内存布局 连续的内存空间。
5. 数组也是值类型。

main.go (验证4)

package main

import "fmt"

func main() {
    var a [10]int
    for i := 0; i < 10; i++ {
        fmt.Printf("%p\n", &a[i])
    }
}
PS D:\project> .\bin\array.exe
0xc0000140f0 // int默认为int64 占用8个字节。
0xc0000140f8
0xc000014100
0xc000014108
0xc000014110
0xc000014118
0xc000014120
0xc000014128
0xc000014130
0xc000014138

(二).数组的遍历

package main

import "fmt"

func main() {
    var a [10]int
    for i := 0; i < len(a); i++ {
        fmt.Printf("%p\n", &a[i])
    }

    var b [20]int
    for index, _ := range b {
        fmt.Printf("b[%d]=%d\n", index, b[index])
    }
}

(三).数组初始化

package main

import (
    "fmt"
    "strings"
)

func testOne() {
    var a [10]int
    for i := 0; i < len(a); i++ {
        fmt.Printf("%p\n", &a[i])
    }

    var b [20]int
    for index, _ := range b {
        fmt.Printf("b[%d]=%d\n", index, b[index])
    }
}

func testTwo() {
    var a [5]int = [5]int{1, 2, 3, 4, 5}
    var b [5]int
    b = a
    fmt.Printf("%v\n", a)
    fmt.Printf("%v\n", b)

    b[0] = 200
    fmt.Println(strings.Repeat("#", 100))
    fmt.Printf("%v\n", a)
    fmt.Printf("%v\n", b)
}

func testThree() {
    var a = [5]int{1, 2, 3, 4, 5}
    var b = [5]int{1, 2, 3}
    var c = [...]int{1, 2, 3, 4, 5, 6, 7}
    var d = [10]string{0: "a", 1: "b"}

    fmt.Printf("%#v\n", a)
    fmt.Printf("%#v\n", b)
    fmt.Printf("%#v\n", c)
    fmt.Printf("%#v\n", d)

}
func main() {
    testThree()
}

(四).二维数组

var arrayName [ x ][ y ] variable_type // var a [8][2]int

1.var a [3][4]int example

row column0 column1 column2 column3
row0 a[0][0] a[0][1] a[0][2] a[0][3]
row1 a[1][0] a[1][1] a[1][2] a[1][3]
row2 a[2][0] a[2][1] a[2][2] a[2][3]

2.初始化并访问二维数组

func testFour() {
    // init
    b := [3][4]int{
        {0, 1, 2, 3},   // index0
        {4, 5, 6, 7},   // index1
        {8, 9, 10, 11}, // index2 此处必须有逗号, last "}" 不能单独一行
    }

    // 访问二维数组
    for x := 0; x < 3; x++ {
        for y := 0; y < 4; y++ {
            fmt.Printf("a[%d][%d]=%d\n", x, y, b[x][y])
        }
    }

}

(五).数组练习

1.生成100个随机 写入到数组 并打印到屏幕

func doExercise1() {
    rand.Seed(time.Now().Unix())
    var c [100]int
    for i := 0; i < 100; i++ {
        randomNumber := rand.Int()
        c[i] = randomNumber
    }
    fmt.Printf("%#v\n", c)
}

2.生成100个随机字符串 写入到数组 并打印到屏幕-课程案例写的太绕自己实现了一个哈。

func doExercise2() {
    var d [100]string
    var b string = "abcdefghijklmnopqrstuvwxyz"
    for i := 0; i < 100; i++ {
        //fmt.Printf("b[%d]=%d %T\n", i, b[i], b[i])
        //fmt.Printf("b[%d]=%s\n", i, string(b[i]))
        d[i] = string(b[rand.Intn(len(b))])

    }
    fmt.Printf("%#v\n", d)

    for i := 0; i < len(d); i++ {
        fmt.Printf("d[%d]=%s\n", i, d[i])
    }
}

二.Slice

(一).slice基础

1.slice没有固定长度。
2.var name []int
3.slice是指针类型或者叫引用类型

main.go

package main

import "fmt"

func testSliceV1() {
    var a [5]int
    var b = a[1:3]
    a[0] = 100
    a[1] = 200
    fmt.Printf("b[0]=%d,b[1]=%d\n", b[0], b[1])
}

func testSliceV2() {
    var a [5]int
    var b = a[1:3]
    b[0] = 100
    b[1] = 200
    fmt.Printf("a[0]=%d,a[1]=%d\n", a[0], a[1])
}

// 求slice元素之和
func sliceSum(a []int) int {
    var initSum int
    for index := range a {
        initSum = initSum + a[index]
        fmt.Printf("a[%d] = %d\n", index, a[index])
    }
    // a[0] = 100
    return initSum
}

func sliceDetail(x []int) {
    fmt.Printf("len[%d],cap[%d],slice:%v\n", len(x), cap(x), x)
}

func arrayCopy(x [5]int) int {
    x[0] = 99
    return x[0]
}

func main() {
    var x []int = []int{1, 2, 3, 4, 100}
    result := sliceSum(x)
    fmt.Printf("sliceSum is %d\n", result)
    sliceDetail(x)

    // test arrayCopy
    arrayV1 := [5]int{1, 2, 3, 4, 5}
    fmt.Println(arrayCopy(arrayV1))
    fmt.Println(arrayV1[0])
}

(二).slice内存布局

slice内存布局

假如slice的cap为5 此时写入的数据为7,slice就会动态扩容,将原来的值拷贝到新的内存区域,其地址会发生改变.

(三).slice初始化底层结构

sliceStruct

make([]type,len,cap)
make([]type,len)
var b []int
b = make([]int,2,5)
// 如果定义了slice的长度和容量超过长度后,会直接报溢出错误
package main

import "fmt"

func sliceDetail(x []int) {
    fmt.Printf("len[%d],cap[%d],slice:%v\n", len(x), cap(x), x)
}

func main() {
    var x []int
    x = make([]int, 5, 5)
    x[0] = 1
    x[1] = 2
    x[2] = 3
    x[3] = 4
    x[4] = 5
    x[5] = 6
    sliceDetail(x)
}

PS D:\project> .\bin\slice2.exe
panic: runtime error: index out of range

goroutine 1 [running]:
main.main()
        D:/project/src/godev2/day3/slice2/main.go:13 +0x77

(四).cap测试

package main

import "fmt"

func sliceDetail(x []int) {
    fmt.Printf("len[%d],cap[%d],slice:%v\n", len(x), cap(x), x)
}

// slice a 长度为5 cap为10,slice b长度为10 容量也为10
func testSliceCap() {
    a := make([]int, 5, 10)
    a[4] = 49
    b := a[0:10]
    b[9] = 99
    fmt.Printf("%#v\n", a)
    fmt.Printf("%#v\n", b)
    sliceDetail(a)
    sliceDetail(b)
}

func main() {
    testSliceCap()
}

result:

[]int{0, 0, 0, 0, 49}
[]int{0, 0, 0, 0, 49, 0, 0, 0, 0, 99}
len[5],cap[10],slice:[0 0 0 0 49]
len[10],cap[10],slice:[0 0 0 0 49 0 0 0 0 99]

(五).sliceExercise

var ar = [10]int{0,1,2,3,4,5,6,7,8,9}
b = ar[5:7]
求b的各个元素以及值长度和容量分别是多少?

b = ar[0:4]
求b的各个元素以及值长度和容量分别是多少?

func testSlice3() {
    ar := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    b := ar[5:7]

    a := ar[0:4]
    sliceDetail(b)
    sliceDetail(a)
}
func main() {
    // testSliceCap()
    testSlice3()
}
// result
PS D:\project> .\bin\slice2.exe
len[2],cap[5],slice:[5 6]  // b
len[4],cap[10],slice:[0 1 2 3] // a

结果分析:
b := ar[5:7] 左指针指向s[5] 右指针指向s[7],slice[start:end]只包含左边 不包含右面 所以长度为2 包含5 6元素。左指针5: 相当于第六位开始 走过了5个元素,容量还剩5.

a := ar[0:4] 左指针指向s[0] 右指针指向s[4] slice[start:end] 即[0,1,2,3] 索引长度为4,但因为左指针未发生变化 所以容量始终为10. 容量问题参考

(六).一个切片在初始化之前默认值为nil,长度为0

var x []int
if x == nil {
    fmt.Println("slice x is nil")
    sliceDetail(x)
}

(七).append()和copy()函数

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

package main

import "fmt"

func sliceDrtail(x []int) {
    fmt.Printf("len=[%d] cap[%d] slice=%#v\n", len(x), cap(x), x)
}

func main() {
    var testSlice []int
    sliceDrtail(testSlice)

    /* 允许追加空切片 */
    testSlice = append(testSlice, 0)
    sliceDrtail(testSlice)

    /* 向切片添加一个元素 */
    testSlice = append(testSlice, 1)
    sliceDrtail(testSlice)

    /* 同时添加多个元素 */
    testSlice = append(testSlice, 2, 3, 4, 5)
    sliceDrtail(testSlice)

    /* 创建切片testSlice1是之前切片的两倍容量*/
    testSlice1 := make([]int, len(testSlice), (cap(testSlice))*2)

    /* 拷贝testSlice的内容到testSlice1*/
    copy(testSlice1, testSlice)
    sliceDrtail(testSlice1)
}
func testCopy() {
    S1 := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    S2 := make([]int, 11)
    copy(S2, S1)
    sliceDetail(S2)
}

func testAppend() {

    /* len=[7] cap[8] slice=[]int{1, 2, 3, 1, 2, 3, 4} */
    a := []int{1, 2, 3}
    a = append(a, 1, 2, 3, 4)
    sliceDetail(a)

    /* len=[0] cap[0] slice=[]int(nil) */
    var b []int
    sliceDetail(b)

    /* len=[9] cap[10] slice=[]int{0, 0, 0, 0, 0, 1, 2, 3, 4} */
    c := make([]int, 5)
    c = append(c, 1, 2, 3, 4)
    sliceDetail(c)
}

// 将a切片添加到b切片里面做法
func testSliceAToSliceB() {
    x := make([]int, 5)
    y := []int{1, 2, 3, 4, 5}
    z := append(x, y...)
    sliceDetail(z)
}

(八)字符串内存布局

字符串不能修改 底层是一个切片 字符串内存布局

1.如何修改一个字符串 实现方式 实现方式 先转换为[]byte 再进行修改 转换。

func testStr() {
    str := "HELLO"
    for index := range str {
        fmt.Printf("index:%d = %v\n", index, string(str[index]))
    }
    /* 先转换为[]byte 修改后再转换为string类型 */
    var b []byte = []byte(str)
    b[0] = 'a'
    str1 := string(b)
    fmt.Printf("str1:%s\n", str1)
}

2.写一段程序实现字符串反转

package main

import "fmt"

func strReverse(str string) {

    b := []rune(str)

    for i := 0; i < len(b)/2; i++ {
        /*
            t := b[i]
            b[i] = b[len(b)-i-1]
            b[len(b)-i-1] = t
        */
        b[i], b[len(b)-i-1] = b[len(b)-i-1], b[i]
    }

    fmt.Println(string(b))
    fmt.Printf("len(b)=%d,len(str)=%d\n", len(b), len(str))
}

func main() {
    strReverse("Hi Jesse伟大从来都不是天生的 是熬出来的。")
}

PS D:\project> .\bin\str.exe
。的来出熬是 的生天是不都来从大伟esseJ iH
len(b)=25,len(str)=57

注释:
type byte = uint8  1个字节。 仅限于acsii的值。
type rune = int32  4个字节。
golang默认使用utf8编码,一个中文占3个字节,一个utf8数字占用1个字节utf8字母占用1个字节。
len(b)=25,len(str)=57 

/* 
len(str)会把每个字母当成一个字符 每个汉字3个字符来计算。
而 每个rune(str)会把每个字母和汉字都当场一个字符来计算。
*/

三.时间和日期

(一).时间测试

package main

import (
    "fmt"
    "time"
)

func testTime() {
    now := time.Now()
    fmt.Printf("type of now is:%T\n", now)

    year := now.Year()
    month := now.Month()
    day := now.Day()
    hour := now.Hour()
    minute := now.Minute()
    second := now.Second()
    /* 02 04 表示宽度 */
    fmt.Printf("%04d/%02d/%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
    fmt.Println(now.Unix())
}

func main() {
    for {
        testTime()
        time.Sleep(time.Second * 1)
    }
}

(二).时间格式化

package main

import (
    "fmt"
    "time"
)

func formatTime() {
    now := time.Now()
    str := now.Format("2006-01-02 15:04:05") // 定义时间格式
    str1 := now.Format("2006/01/02 15:04:05")
    str2 := now.Format("02/01/2006 15:04:05")
    fmt.Printf("format result:%s\n", str)
    fmt.Printf("format result:%s\n", str1)
    fmt.Printf("format result:%s\n", str2)
}

func main() {
    formatTime()
}

三.作业

常见问题答疑:
>>> 9/2 // 整数与整数之间运算的结果必然是整数,就算是除法也会执行整除而舍弃小数。所以9/2的结果是4
4
>>> 9/2.0 // 整数与浮点数的运算会转化为浮点类型再进行运算,其结果应是浮点类型,所以9/2.0的结果是 4.5
4.5

homework3

package main

import "fmt"

func MultiplicationTable() {
    for i := 0; i <= 9; i++ {
        for j := 0; j <= i; j++ {
            fmt.Printf("%d * %d = %d\t", i, j, i*j)
        }
        fmt.Println()
    }
}

func isPerfectNumber(n int) bool {

    if n <= 0 {
        return false
    }

    var result int
    for i := 1; i < n; i++ {
        if n%i == 0 {
            result = result + i
        }
    }

    if result == n {
        return true
    }

    return false
}

func isPalindromeNumber(str string) bool {
    for i := 0; i < len(str)/2; i++ {
        if str[i] != str[len(str)-i-1] {
            fmt.Println(str[i])
            return false
            break
        }
    }
    return true
}

// 4.string count
func countStr(str string) (strCount, blankCount, numCount, otherCount int) {
    t := []rune(str)
    for _, value := range t {
        switch {
        case value >= 'a' && value <= 'z':
            strCount++
        case value >= 'A' && value <= 'Z':
            strCount++
        case value == ' ':
            blankCount++
        case value >= 0 && value <= 9:
            numCount++
        default:
            otherCount++
        }
    }
    return
}

func main() {
    // MultiplicationTable()
    for i := 1; i <= 1000; i++ {
        if isPerfectNumber(i) == true {
            fmt.Printf("%d\n", i)
        }
    }

    if isPalindromeNumber("asssssssa") == true {
        fmt.Println("121")
    }

    // string count
    sc, bc, nc, oc := countStr("baidu.com12  ")
    fmt.Println(sc, bc, nc, oc)
}
Copyright © zhangluya.com 2019            UPDATE 2020-03-26 15:42:33

results matching ""

    No results matching ""