一、Array
数组和切片是 Go 语言中最常见的数据结构。
数组是由相同类型的元素的集合的数据结构,被分配一块的连续的内存用来保存数据,且可以通过其中存储的索引进行快速访问其存储地址。
1-1 Array 的初始化
Array 是定长的,一旦初始化后,无法改变其长度大小;而 Slice 是不定长的Array。
array 的初始化有两种方式:1、显式指定长度 2、使用可变参数,由语言推断长度
arr1 := [3]int{
1, 2, 3}
arr2 := [...]int{
1, 2, 3}
arr3 := [10]int{
} // 10 长度,元素为初始值的数组
两种初始化的方式,主要体现在编译器创建对应 array 的位置。
显式指定长度:编译器会在类型检查阶段就能提出变量的类型
可变参数推断长度:声明时,默认数组的大小上限为 -1,-1 作为一个占位符。编译器会在后续编译过程中将使用可变参数的 Array 定义为 DDDArray,使用遍历元素的方式计算数组中元素的数量。
1-1-1 Array 的初始化可指定索引和对应值
import (
"fmt"
)
func main(){
arrayA := [...]int{
0:1, 2:1, 3:4}
fmt.Println(arrayA) // [1 0 1 4]
fmt.Println(len(arrayA)) // 4
}
技巧:可通过仅定义 array 最后一个元素的值,来初始化长度。
package main
import (
"fmt"
)
func main(){
arrayA := [...]int{
9:1}
// or,arrayA := [10]int{}
fmt.Println(arrayA) //[0 0 0 0 0 0 0 0 0 1]
fmt.Println(len(arrayA)) // 10
}
1-2 Array 的访问和赋值
1-2-1 range 循环 Array 返回索引和值
package main
import "fmt"
func main() {
x := []string{
"a","b","c"}
for _, v := range x {
fmt.Println(v) //prints a, b, c
}
}
1-3 不同长度的 Array 是不同的类型
Array 长度是数组类型的一个组成部分,因此 [3] int 和 [4] int 是不同的数组类型.
但是确认长度的数组 都属于 array 类型,所以 kind() 相同,可以通过 kind 进行判断
package main
import (
"fmt"
"reflect"
)
func main() {
arrayA := [...]int{
1, 2, 3}
arrayB := [...]int{
1, 2, 3, 4}
fmt.Println(reflect.TypeOf(arrayA))
// or
//fmt.Printf("%T", arrayA)
fmt.Println(reflect.TypeOf(arrayB))
fmt.Println(reflect.TypeOf(arrayA) == reflect.TypeOf(arrayB))
/*
[3]int
[4]int
false
*/
fmt.Println(reflect.TypeOf(arrayA).Kind())
fmt.Println(reflect.TypeOf(arrayB).Kind())
/*
array
array
*/
fmt.Println(reflect.DeepEqual(reflect.TypeOf(arrayA).Kind(),reflect.TypeOf(arrayB).Kind()))
fmt.Println(reflect.TypeOf(arrayA).Kind().String() == "array")
/*
true
true
*/
}
slice 是不定长的 array,所以即使长度不同,也为同一个类型
package main
import (
"fmt"
"reflect"
)
func main() {
arrayC :=[]int{
1,2,3}
arrayD :=[]int{
1,2,3,4}
fmt.Println(reflect.TypeOf(arrayC)) // []int
fmt.Println(reflect.TypeOf(arrayC).Kind()) // slice
fmt.Println(reflect.TypeOf(arrayC) == reflect.TypeOf(arrayD)) // true
}
1-4 函数中 Array 参数是值传递
Go 中的数组传参时,是值传递,函数会的到原始数据的一份赋值数据,而非同一个内存地址。
package main
import "fmt"
func main() {
x := [3]int{
1,2,3}
func(arr [3]int) {
arr[0] = 7
fmt.Println(arr) //prints [7 2 3]
}(x)
fmt.Println(x)
//prints [1 2 3] (not ok if you need [7 2 3])
}
若需要使用同一个内存地址时,应该使用数组指针类型传参,引用传递。
package main
import "fmt"
func main() {
x := [3]int{
1,2,3}
// 指向参数 x
func(arr *[3]int) {
(*arr)[0] = 7
fmt.Println(arr) //prints &[7 2 3]
}(&x)
fmt.Println(x) //prints [7 2 3]