长亭百川云 - 文章详情

Golang 中的数组与切片

RedTeam

35

2024-07-13

0x00 数组

  • 声明数组的方式

  • 固定长度的数组在传递参数时需严格匹配数组类型、长度

  • 函数的形参为数组时,其拷贝方式为值拷贝

`package main      import (    "fmt"   )      func printArray(myArray [4]int) {    // 值拷贝    for index, value := range myArray {     fmt.Println("index = ", index, " , value = ", value)    }       myArray[0] = 233   }      func main() {       // 固定长度数组    var myArray1 [10]int    var myArray2 [10]float32       myArray3 := [10]int{1, 2, 3, 4}       myArray4 := [4]int{11, 22, 33, 44}       // for i := 0; i < 10; i ++ {    for i := 0; i < len(myArray1); i++ {     fmt.Println(myArray1[i])       }       fmt.Println("===== ===== ===== =====")       for j := 0; j < len(myArray2); j++ {     fmt.Println(myArray2[j])    }       fmt.Println("===== ===== ===== =====")       for index, value := range myArray3 {     fmt.Println("index= ", index, ", value = ", value)    }       // 查看数组的数据类型    fmt.Printf("myArray1 types = %T\n", myArray1)    fmt.Printf("myArray2 types = %T\n", myArray2)    fmt.Printf("myArray3 types = %T\n", myArray3)    fmt.Printf("myArray4 types = %T\n", myArray4)       fmt.Println("===== ===== ===== =====")       printArray(myArray4)       fmt.Println("=====")       for index, value := range myArray4 {     fmt.Println("index = ", index, ", value = ", value)    }   }      `

image

image

0x01 slice

  • slice 切片,动态数组。

  • 在定义函数时,我们通常希望形参的数据类型更通用,数组是固定长度的,slice 切片是动态数组,形参直接定义为 slice 即可。

  • 动态数组在函数传参时为引用传递

  • 不同元素长度的动态数组,传参的形参是一致的

`package main      import (    "fmt"   )      // func printArray(myArray [4]int) {   //  // 值拷贝   //  for index, value := range myArray {   //   fmt.Println("index = ", index, " , value = ", value)   //  }      //  myArray[0] = 233   // }      func printSlice(myArray []int) {    // 引用传递    // Slice 和 数组相比的一个好处是可变长度,这为形参的参数值长度提供了更多的可能性,更加灵活了    // 动态数组是指向数组内存的指针(引用)    for _, value := range myArray {     fmt.Println("value = ", value)    }    myArray[0] = 233   }      func main() {       // // 固定长度数组    // var myArray1 [10]int    // var myArray2 [10]float32       // myArray3 := [10]int{1, 2, 3, 4}       // myArray4 := [4]int{11, 22, 33, 44}       // // for i := 0; i < 10; i ++ {    // for i := 0; i < len(myArray1); i++ {    //  fmt.Println(myArray1[i])       // }       // fmt.Println("===== ===== ===== =====")       // for j := 0; j < len(myArray2); j++ {    //  fmt.Println(myArray2[j])    // }       // fmt.Println("===== ===== ===== =====")       // for index, value := range myArray3 {    //  fmt.Println("index= ", index, ", value = ", value)    // }       // // 查看数组的数据类型    // fmt.Printf("myArray1 types = %T\n", myArray1)    // fmt.Printf("myArray2 types = %T\n", myArray2)    // fmt.Printf("myArray3 types = %T\n", myArray3)    // fmt.Printf("myArray4 types = %T\n", myArray4)       // fmt.Println("===== ===== ===== =====")       // printArray(myArray4)       // fmt.Println("=====")       // for index, value := range myArray4 {    //  fmt.Println("index = ", index, ", value = ", value)    // }    // var myArray5 [10]int    myArray := []int{1, 2, 3, 4} // 动态数组 切片 slice    fmt.Printf("myArray type is %T\n", myArray)       printSlice(myArray)       fmt.Println("===== ===== ===== =====")       // printSlice(myArray5)       for _, value := range myArray {     fmt.Println("value = ", value)    }   }      `

image

0x02 slice 的 4 种声明定义方式

`package main      import (    "fmt"   )      // func printArray(myArray [4]int) {   //  // 值拷贝   //  for index, value := range myArray {   //   fmt.Println("index = ", index, " , value = ", value)   //  }      //  myArray[0] = 233   // }      // func printSlice(myArray []int) {   //  // 引用传递   //  // Slice 和 数组相比的一个好处是可变长度,这为形参的参数值长度提供了更多的可能性,更加灵活了   //  // 动态数组是指向数组内存的指针(引用)   //  for _, value := range myArray {   //   fmt.Println("value = ", value)   //  }   //  myArray[0] = 233   // }      func main() {       // // 固定长度数组    // var myArray1 [10]int    // var myArray2 [10]float32       // myArray3 := [10]int{1, 2, 3, 4}       // myArray4 := [4]int{11, 22, 33, 44}       // // for i := 0; i < 10; i ++ {    // for i := 0; i < len(myArray1); i++ {    //  fmt.Println(myArray1[i])       // }       // fmt.Println("===== ===== ===== =====")       // for j := 0; j < len(myArray2); j++ {    //  fmt.Println(myArray2[j])    // }       // fmt.Println("===== ===== ===== =====")       // for index, value := range myArray3 {    //  fmt.Println("index= ", index, ", value = ", value)    // }       // // 查看数组的数据类型    // fmt.Printf("myArray1 types = %T\n", myArray1)    // fmt.Printf("myArray2 types = %T\n", myArray2)    // fmt.Printf("myArray3 types = %T\n", myArray3)    // fmt.Printf("myArray4 types = %T\n", myArray4)       // fmt.Println("===== ===== ===== =====")       // printArray(myArray4)       // fmt.Println("=====")       // for index, value := range myArray4 {    //  fmt.Println("index = ", index, ", value = ", value)    // }    // var myArray5 [10]int    // myArray := []int{1, 2, 3, 4} // 动态数组 切片 slice    // fmt.Printf("myArray type is %T\n", myArray)       // printSlice(myArray)       // fmt.Println("===== ===== ===== =====")       // // printSlice(myArray5)       // for _, value := range myArray {    //  fmt.Println("value = ", value)    // }       // 声明 slice 的 4 种方法       // 1. 声明 slice1 是一个切片,并且初始化,默认值是 1, 2, 3,长度 len 是 3    slice1 := []int{1, 2, 3}    fmt.Printf("len = %d, slice1 = %v\n", len(slice1), slice1)       // 2. 声明 slice2 是一个切片,但是此时并未给 slice2 分配内存空间    // 此时无法为 slice2[0] = 1 赋值,会提示越界错误    var slice2 []int       // 可以通过 make 开辟内存空间    slice2 = make([]int, 3)    slice2[0] = 233    fmt.Printf("len = %d, slice2 = %v\n", len(slice2), slice2)       // 3. 声明 slice3 是一个切片,同时为 slice3 分配内存空间,3 个空间,初始化值为 0    var slice3 []int = make([]int, 3)    fmt.Printf("len = %d, slice3 = %v\n", len(slice3), slice3)        // 4. 声明 slice4 是一个切片,同时为 slice4 分配内存空间,4 个空间,初始化值为 0,通过 := 推导出 slice4 是一个切片    slice4 := make([]int, 4)    fmt.Printf("len = %d, slice4 = %v\n", len(slice4), slice4)       // 判断 slice 是否为空    var slice5 []int    if slice5 == nil {     fmt.Println("slice5 is nil,是一个空切片")    } else {     fmt.Println("slice5 是有空间的")    }      }      `

image

0x03 slice 切片容量的追加

切片的长度(len)和容量(cap)不同,长度表示左指针及右指针之间的距离,容量表示左指针至底层数组末尾的距离。

image

切片的扩容机制,append() 的时候,如果长度增加后超过容量,则将容量增加 2 倍。

`package main      import (    "fmt"   )      // func printArray(myArray [4]int) {   //  // 值拷贝   //  for index, value := range myArray {   //   fmt.Println("index = ", index, " , value = ", value)   //  }      //  myArray[0] = 233   // }      // func printSlice(myArray []int) {   //  // 引用传递   //  // Slice 和 数组相比的一个好处是可变长度,这为形参的参数值长度提供了更多的可能性,更加灵活了   //  // 动态数组是指向数组内存的指针(引用)   //  for _, value := range myArray {   //   fmt.Println("value = ", value)   //  }   //  myArray[0] = 233   // }      func main() {       // // 固定长度数组    // var myArray1 [10]int    // var myArray2 [10]float32       // myArray3 := [10]int{1, 2, 3, 4}       // myArray4 := [4]int{11, 22, 33, 44}       // // for i := 0; i < 10; i ++ {    // for i := 0; i < len(myArray1); i++ {    //  fmt.Println(myArray1[i])       // }       // fmt.Println("===== ===== ===== =====")       // for j := 0; j < len(myArray2); j++ {    //  fmt.Println(myArray2[j])    // }       // fmt.Println("===== ===== ===== =====")       // for index, value := range myArray3 {    //  fmt.Println("index= ", index, ", value = ", value)    // }       // // 查看数组的数据类型    // fmt.Printf("myArray1 types = %T\n", myArray1)    // fmt.Printf("myArray2 types = %T\n", myArray2)    // fmt.Printf("myArray3 types = %T\n", myArray3)    // fmt.Printf("myArray4 types = %T\n", myArray4)       // fmt.Println("===== ===== ===== =====")       // printArray(myArray4)       // fmt.Println("=====")       // for index, value := range myArray4 {    //  fmt.Println("index = ", index, ", value = ", value)    // }    // var myArray5 [10]int    // myArray := []int{1, 2, 3, 4} // 动态数组 切片 slice    // fmt.Printf("myArray type is %T\n", myArray)       // printSlice(myArray)       // fmt.Println("===== ===== ===== =====")       // // printSlice(myArray5)       // for _, value := range myArray {    //  fmt.Println("value = ", value)    // }       // // 声明 slice 的 4 种方法       // // 1. 声明 slice1 是一个切片,并且初始化,默认值是 1, 2, 3,长度 len 是 3    // slice1 := []int{1, 2, 3}    // fmt.Printf("len = %d, slice1 = %v\n", len(slice1), slice1)       // // 2. 声明 slice2 是一个切片,但是此时并未给 slice2 分配内存空间    // // 此时无法为 slice2[0] = 1 赋值,会提示越界错误    // var slice2 []int       // // 可以通过 make 开辟内存空间    // slice2 = make([]int, 3)    // slice2[0] = 233    // fmt.Printf("len = %d, slice2 = %v\n", len(slice2), slice2)       // // 3. 声明 slice3 是一个切片,同时为 slice3 分配内存空间,3 个空间,初始化值为 0    // var slice3 []int = make([]int, 3)    // fmt.Printf("len = %d, slice3 = %v\n", len(slice3), slice3)       // // 4. 声明 slice4 是一个切片,同时为 slice4 分配内存空间,4 个空间,初始化值为 0,通过 := 推导出 slice4 是一个切片    // slice4 := make([]int, 4)    // fmt.Printf("len = %d, slice4 = %v\n", len(slice4), slice4)       // // 判断 slice 是否为空    // var slice5 []int    // if slice5 == nil {    //  fmt.Println("slice5 is nil,是一个空切片")    // } else {    //  fmt.Println("slice5 是有空间的")    // }       // slice 切片的长度是 3,容量是 5    var slice6 = make([]int, 3, 5)       fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // 向 slice6 中添加元素 1,此时 len = 4,cap = 5,[0 0 0 1]    slice6 = append(slice6, 1)       fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       slice6 = append(slice6, 2)    fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // 像一个 slice 容量满了的 slice 中追加元素,Golang 会在底层开辟一定量等长的内存空间,如 原来的容量是 5,则现在的容量为 10    // cap = 10    slice6 = append(slice6, 3)    fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       fmt.Println("===== ===== ===== ===== =====")       // 如果没指定 cap,则 cap = len    var number2 = make([]int, 3)    fmt.Printf("len = %d, cap = %d, number2 = %v\n", len(number2), cap(number2), number2)       // cap = 6    number2 = append(number2, 111)    fmt.Printf("len = %d, cap = %d, number2 = %v\n", len(number2), cap(number2), number2)      }      `

image

0x04 slice 切片容量的截取

slice 截取后,两个 slice 仍然指向相同的内存空间。可以通过 copy() 函数,将两个 slice 指向不同的内存空间。(深拷贝,拷贝一个副本,将底层数组的 slice 一起进行拷贝。)

`package main      import (    "fmt"   )      // func printArray(myArray [4]int) {   //  // 值拷贝   //  for index, value := range myArray {   //   fmt.Println("index = ", index, " , value = ", value)   //  }      //  myArray[0] = 233   // }      // func printSlice(myArray []int) {   //  // 引用传递   //  // Slice 和 数组相比的一个好处是可变长度,这为形参的参数值长度提供了更多的可能性,更加灵活了   //  // 动态数组是指向数组内存的指针(引用)   //  for _, value := range myArray {   //   fmt.Println("value = ", value)   //  }   //  myArray[0] = 233   // }      func main() {       // // 固定长度数组    // var myArray1 [10]int    // var myArray2 [10]float32       // myArray3 := [10]int{1, 2, 3, 4}       // myArray4 := [4]int{11, 22, 33, 44}       // // for i := 0; i < 10; i ++ {    // for i := 0; i < len(myArray1); i++ {    //  fmt.Println(myArray1[i])       // }       // fmt.Println("===== ===== ===== =====")       // for j := 0; j < len(myArray2); j++ {    //  fmt.Println(myArray2[j])    // }       // fmt.Println("===== ===== ===== =====")       // for index, value := range myArray3 {    //  fmt.Println("index= ", index, ", value = ", value)    // }       // // 查看数组的数据类型    // fmt.Printf("myArray1 types = %T\n", myArray1)    // fmt.Printf("myArray2 types = %T\n", myArray2)    // fmt.Printf("myArray3 types = %T\n", myArray3)    // fmt.Printf("myArray4 types = %T\n", myArray4)       // fmt.Println("===== ===== ===== =====")       // printArray(myArray4)       // fmt.Println("=====")       // for index, value := range myArray4 {    //  fmt.Println("index = ", index, ", value = ", value)    // }    // var myArray5 [10]int    // myArray := []int{1, 2, 3, 4} // 动态数组 切片 slice    // fmt.Printf("myArray type is %T\n", myArray)       // printSlice(myArray)       // fmt.Println("===== ===== ===== =====")       // // printSlice(myArray5)       // for _, value := range myArray {    //  fmt.Println("value = ", value)    // }       // // 声明 slice 的 4 种方法       // // 1. 声明 slice1 是一个切片,并且初始化,默认值是 1, 2, 3,长度 len 是 3    // slice1 := []int{1, 2, 3}    // fmt.Printf("len = %d, slice1 = %v\n", len(slice1), slice1)       // // 2. 声明 slice2 是一个切片,但是此时并未给 slice2 分配内存空间    // // 此时无法为 slice2[0] = 1 赋值,会提示越界错误    // var slice2 []int       // // 可以通过 make 开辟内存空间    // slice2 = make([]int, 3)    // slice2[0] = 233    // fmt.Printf("len = %d, slice2 = %v\n", len(slice2), slice2)       // // 3. 声明 slice3 是一个切片,同时为 slice3 分配内存空间,3 个空间,初始化值为 0    // var slice3 []int = make([]int, 3)    // fmt.Printf("len = %d, slice3 = %v\n", len(slice3), slice3)       // // 4. 声明 slice4 是一个切片,同时为 slice4 分配内存空间,4 个空间,初始化值为 0,通过 := 推导出 slice4 是一个切片    // slice4 := make([]int, 4)    // fmt.Printf("len = %d, slice4 = %v\n", len(slice4), slice4)       // // 判断 slice 是否为空    // var slice5 []int    // if slice5 == nil {    //  fmt.Println("slice5 is nil,是一个空切片")    // } else {    //  fmt.Println("slice5 是有空间的")    // }       // // slice 切片的长度是 3,容量是 5    // var slice6 = make([]int, 3, 5)       // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // // 向 slice6 中添加元素 1,此时 len = 4,cap = 5,[0 0 0 1]    // slice6 = append(slice6, 1)       // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // slice6 = append(slice6, 2)    // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // // 像一个 slice 容量满了的 slice 中追加元素,Golang 会在底层开辟一定量等长的内存空间,如 原来的容量是 5,则现在的容量为 10    // // cap = 10    // slice6 = append(slice6, 3)    // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // fmt.Println("===== ===== ===== ===== =====")       // // 如果没指定 cap,则 cap = len    // var number2 = make([]int, 3)    // fmt.Printf("len = %d, cap = %d, number2 = %v\n", len(number2), cap(number2), number2)       // // cap = 6    // number2 = append(number2, 111)    // fmt.Printf("len = %d, cap = %d, number2 = %v\n", len(number2), cap(number2), number2)       // len = 3, cap = 3    s := []int{111, 222, 333}       // 左闭右开 [0, 1)    s1 := s[0:1]       fmt.Printf("s1 = %v \n", s1)       // [0, 2) [111, 222]    s2 := s[0:2]    fmt.Printf("s2 = %v \n", s2)       // 表示截取全部元素    s3 := s[:]    fmt.Printf("s3 = %v \n", s3)       // 默认下限为 0, [111 222]    s4 := s[:2]    fmt.Printf("s4 = %v \n", s4)       // 默认上限为 len()  [222 333]       s5 := s[1:]    fmt.Printf("s5 = %v \n", s5)       // slice 截取后,两个 slice 仍然指向相同的内存空间    s1[0] = 888    fmt.Printf("new s = %v \n", s)       fmt.Println("===== ===== ===== ===== =====")       // c2 = [0 0 0]    c2 := make([]int, 3)       // 将 s 中的值依次拷贝值 c2 中    // 此时 c2 与 s 是完全不同的内存空间(新内存空间)    copy(c2, s)    fmt.Printf("c2 = %v \n", c2)      }      `

image

0x05 相关疑问

  1. 数组可以类似切片一样通过 s[1:3] 的方式截取吗?

可以,此时新截取的变量类型为 slice。

`package main      import (    "fmt"   )      // func printArray(myArray [4]int) {   //  // 值拷贝   //  for index, value := range myArray {   //   fmt.Println("index = ", index, " , value = ", value)   //  }      //  myArray[0] = 233   // }      // func printSlice(myArray []int) {   //  // 引用传递   //  // Slice 和 数组相比的一个好处是可变长度,这为形参的参数值长度提供了更多的可能性,更加灵活了   //  // 动态数组是指向数组内存的指针(引用)   //  for _, value := range myArray {   //   fmt.Println("value = ", value)   //  }   //  myArray[0] = 233   // }      func main() {       // // 固定长度数组    // var myArray1 [10]int    // var myArray2 [10]float32       // myArray3 := [10]int{1, 2, 3, 4}       // myArray4 := [4]int{11, 22, 33, 44}       // // for i := 0; i < 10; i ++ {    // for i := 0; i < len(myArray1); i++ {    //  fmt.Println(myArray1[i])       // }       // fmt.Println("===== ===== ===== =====")       // for j := 0; j < len(myArray2); j++ {    //  fmt.Println(myArray2[j])    // }       // fmt.Println("===== ===== ===== =====")       // for index, value := range myArray3 {    //  fmt.Println("index= ", index, ", value = ", value)    // }       // // 查看数组的数据类型    // fmt.Printf("myArray1 types = %T\n", myArray1)    // fmt.Printf("myArray2 types = %T\n", myArray2)    // fmt.Printf("myArray3 types = %T\n", myArray3)    // fmt.Printf("myArray4 types = %T\n", myArray4)       // fmt.Println("===== ===== ===== =====")       // printArray(myArray4)       // fmt.Println("=====")       // for index, value := range myArray4 {    //  fmt.Println("index = ", index, ", value = ", value)    // }    // var myArray5 [10]int    // myArray := []int{1, 2, 3, 4} // 动态数组 切片 slice    // fmt.Printf("myArray type is %T\n", myArray)       // printSlice(myArray)       // fmt.Println("===== ===== ===== =====")       // // printSlice(myArray5)       // for _, value := range myArray {    //  fmt.Println("value = ", value)    // }       // // 声明 slice 的 4 种方法       // // 1. 声明 slice1 是一个切片,并且初始化,默认值是 1, 2, 3,长度 len 是 3    // slice1 := []int{1, 2, 3}    // fmt.Printf("len = %d, slice1 = %v\n", len(slice1), slice1)       // // 2. 声明 slice2 是一个切片,但是此时并未给 slice2 分配内存空间    // // 此时无法为 slice2[0] = 1 赋值,会提示越界错误    // var slice2 []int       // // 可以通过 make 开辟内存空间    // slice2 = make([]int, 3)    // slice2[0] = 233    // fmt.Printf("len = %d, slice2 = %v\n", len(slice2), slice2)       // // 3. 声明 slice3 是一个切片,同时为 slice3 分配内存空间,3 个空间,初始化值为 0    // var slice3 []int = make([]int, 3)    // fmt.Printf("len = %d, slice3 = %v\n", len(slice3), slice3)       // // 4. 声明 slice4 是一个切片,同时为 slice4 分配内存空间,4 个空间,初始化值为 0,通过 := 推导出 slice4 是一个切片    // slice4 := make([]int, 4)    // fmt.Printf("len = %d, slice4 = %v\n", len(slice4), slice4)       // // 判断 slice 是否为空    // var slice5 []int    // if slice5 == nil {    //  fmt.Println("slice5 is nil,是一个空切片")    // } else {    //  fmt.Println("slice5 是有空间的")    // }       // // slice 切片的长度是 3,容量是 5    // var slice6 = make([]int, 3, 5)       // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // // 向 slice6 中添加元素 1,此时 len = 4,cap = 5,[0 0 0 1]    // slice6 = append(slice6, 1)       // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // slice6 = append(slice6, 2)    // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // // 像一个 slice 容量满了的 slice 中追加元素,Golang 会在底层开辟一定量等长的内存空间,如 原来的容量是 5,则现在的容量为 10    // // cap = 10    // slice6 = append(slice6, 3)    // fmt.Printf("len = %d, cap = %d, slice6 = %v\n", len(slice6), cap(slice6), slice6)       // fmt.Println("===== ===== ===== ===== =====")       // // 如果没指定 cap,则 cap = len    // var number2 = make([]int, 3)    // fmt.Printf("len = %d, cap = %d, number2 = %v\n", len(number2), cap(number2), number2)       // // cap = 6    // number2 = append(number2, 111)    // fmt.Printf("len = %d, cap = %d, number2 = %v\n", len(number2), cap(number2), number2)       // // len = 3, cap = 3    // s := []int{111, 222, 333}       // // 左闭右开 [0, 1)    // s1 := s[0:1]       // fmt.Printf("s1 = %v \n", s1)       // // [0, 2) [111, 222]    // s2 := s[0:2]    // fmt.Printf("s2 = %v \n", s2)       // // 表示截取全部元素    // s3 := s[:]    // fmt.Printf("s3 = %v \n", s3)       // // 默认下限为 0, [111 222]    // s4 := s[:2]    // fmt.Printf("s4 = %v \n", s4)       // // 默认上限为 len()  [222 333]       // s5 := s[1:]    // fmt.Printf("s5 = %v \n", s5)       // // slice 截取后,两个 slice 仍然指向相同的内存空间    // s1[0] = 888    // fmt.Printf("new s = %v \n", s)       // fmt.Println("===== ===== ===== ===== =====")       // // c2 = [0 0 0]    // c2 := make([]int, 3)       // // 将 s 中的值依次拷贝值 c2 中    // // 此时 c2 与 s 是完全不同的内存空间(新内存空间)    // copy(c2, s)    // fmt.Printf("c2 = %v \n", c2)       var arr1 [5]int    arr1 = [5]int{111, 222, 333, 444, 555}    fmt.Printf("arr1 = %v \n", arr1)       arr2 := arr1[2:4]    fmt.Printf("arr2 = %v \n", arr2)       fmt.Printf("arr1 type = %T \n", arr1)    fmt.Printf("arr2 type = %T \n", arr2)      }      `

image

0x06 References

  1. https://www.bilibili.com/video/BV1gf4y1r79E?p=14&spm\_id\_from=pageDriver
相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2