Go Array Slice

go array

  1. 数组是值类型,赋值和传参会复制整个数组,而不是指针。
  2. 数组长度必须是常量,且是类型的组成部分。[2]int和[3]int是不同类型。
  3. 支持==!=操作符,因为内存总是被初始化过的。
    aq14. 指针数组:[n]*T, 数组指正: *[n]t

go 数组声明与初始化

  • 数组声明

    1
    2
       var arr [5]int
    var arr1 = new([5]int)
  • 初始化赋值

    1
    2
    3
    var arr3 = [5]int{1,2,3}    // 未初始化元素值为 0
    var arr2 = [...]string{"a","b","c"} // 通过初始化值确定数组⻓长度
    c := [5]int{2: 100, 4:200} // 使⽤用索引号初始化元素
  • 多维数组

    1
    2
    a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能⽤用 "..."
  • 声明赋值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
       a := [2]int{1} //长度2 只赋一个值
    a[1] = 3
    fmt.Println(a) //[1 3]

    b := [5]int{4:1}
    fmt.Println(b) //[0 0 0 0 1]

    c := [...]int{9:1} //不定长
    fmt.Println(c) //[0 0 0 0 0 0 0 0 0 1]

    d := [10]int{}
    d[1] = 2
    fmt.Println(d)

    e := new([10]int)
    e[1] = 2
    fmt.Println(e)
  • 内置函数lencap都返回数组长度

    1
    2
    a := [2]int{}
    println(len(a), cap(a)) // 2, 2

go slice

  • 切片是一个长度可变的数组
  • 优点 因为切片是引用,所以他们不需要使用额外的内存并且比使用数组更有效,所以在go中切片比数组更常使用.
  • slice并不是数组或数组指正。它通过内部指针和相关属性引用数组片段,以实现变长方案。
  • 属性len标示可用元素数量,读写操作不能超过该限制。
  • 属性cap表示最大扩容量,不能超出数组限制
  • 如果slice == nil ,那么len、cap结果都等于0
  • 声明
    1
    2
    3
    4
    5
    6
       //var slice []type = array[strat:end]
    //var slice1 []type = arr1[:] //那么 slice1 就等于完整的 arr1 数组 arr1[0:len(arr1)
    //arr1[2:] 和 arr1[2:len(arr1)] //相同,都包含了数组从第三个到最后的所有元素。
    //arr1[:3] 和 arr1[0:3] //相同,包含了从第一个到第三个元素(不包括第三个
    //slice1 = slice1[:len(slice1)-1] //去掉最后一个元素

  • 初始化
    1
    2
    3
       s := [3]int{1,2,3}
    s1 := []int{1,2,3}
    fmt.Print(s,s1)
  • 数组初始化 slice 切片数组
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
       var arr [6]int
    var slice []int = arr[2:5]
    fmt.Println(slice)
    //遍历数组
    for i:=0;i<len(arr);i++{
    arr[i] = i
    }
    fmt.Println(arr)
    // slice 是应用类型 改变arr slice也就变了
    for i:=0;i<len(slice);i++{
    fmt.Println(slice[i])
    }
1
2
3
4
5
6
7
   b := []byte{'g','o','i','a','q','l'}
fmt.Print(string(b[0:5]))

//切片传递
var arr = [5]int{0,1,2,3,4}
num := sum(arr[:])
fmt.Println(num)
  • make 创建切片
    1
    2
    3
    4
    5
    // 语法 var slice []type = make([]type,len)
    //var slice []int = make([]int ,10,100)
    //fmt.Println(slice)
    //fmt.Println(len(slice))
    //fmt.Println(cap(slice))
  • make 和 new 的区别

    都在堆上分配内存,但运行行为不同,适用于不同的类型
    new(t) 分配内存 初始化0 并且返回*t的内存地址,这种方法返回一个指向类型为t,值为0 的地址的指针,使用与值类型 如数组和结构体
    new函数分配内存
    make(t) 返回一个类型为t的初始值 只使用与3中内建的引用类型 : 切片、map channel
    make函数初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//s := make([]byte,5);
//fmt.Println(len(s)) //5
//s1 := s[2:4]
//fmt.Println(len(s1),cap(s1)) // 2 3

//引用类型
//s1 := []byte{'p', 'o', 'e', 'm'}
//s2 := s1[2:]
////fmt.Println(s2)
//s2[1] = 't'
//fmt.Println(string(s1))
//fmt.Println(string(s2))

//var ar = [10]int{0,1,2,3,4,5,6,7,8,9}
//var a = ar[5:7]
//fmt.Println(a)
//a = a[0:4]
//fmt.Println(a) //引用类型 值取决于 切片数组而不是依据上次切片

//fmt.Println(len(ar),cap(ar))
//r := ar[2:2] //len 0 cap 取决与截取后剩余多少个
//r1 := ar[2:2+1] //len 1 cap 取决与从开始截取位置到截取后剩余多少个
//fmt.Println(len(r),cap(r))
//fmt.Println(len(r1),cap(r1))


//赋值 与追加
//a := []int{1,2,3}
//a1 := make([]int,10)
//n := copy(a1,a) //将 a 拷贝给a1
//fmt.Println(n)
//fmt.Print(a1)


//s := "\u00ff\u754c"
//for i, c := range s {
// fmt.Printf("%d:%c ", i, c)
//}


//str1 := "asSASA ddd dsjkdsjs dk"
//fmt.Println(len(str1))
//fmt.Println(utf8.RuneCountInString(str1))
//str2 := "asSASA ddd dsjkdsjsこん dk"
//fmt.Println(len(str2))
//fmt.Println(utf8.RuneCountInString(str2))
//
////var b []byte
////var s string
////b = append(b, s...)
////fmt.Println(b)
//
//s := "hello"
//c := []byte(s)
//c[0] = 'c'
//s2 := string(c) // s2 == "cello"
//
//fmt.Print(s2)