Go 语言支持复合类型:
- 数组:array
- 切片:slice
- 指针:pointer
- 字典:map
- 通道:chan
- 结构体:struct
- 接口:interface
1. array
同一类型数据的集合
var arr [n]type //声明type类型一维数组
var arr [m][n]type //声明type类型二维数组
多维数组以此类推
也可以用 := 声明
arr := [n]type{元素1[,元素2, ...]} 其中n可以用 "..." 三个点表示,系统会根据元素个数来确定
下标只能为 int 类型,而 php 还支持 string 类型的下标
1.1 数组长度 len(arr)
注:数组长度在定义后就不可变
1.2 遍历:
a. 循环通过过数组下标访问 arr[0] ~ arr[(len(arr))]
b. range arr, 有两个返回值 第一个为数组下标,第二个为元素的值,与php遍历数组相似
for k, v := range array { fmt.Printf("arr[%d] = %d ", k, v) }
foreach ($arr as $k => $v) { printf("arr[%d] = %d ", $k, $v); //echo '$arr[' . $k . "] = " . $v . " "; }
1.3 数组在赋值与传递参数时,都会产生一个数组副本,而不是使用它的指针
2. slice
在定义 array 时,其长度是固定的,并且 array 是一个值类型
而 slice 是一个可变的数组,但是一个引用类型
2.1 产生slice的三种方式
a. 声明与 array 一样,不过不需要指定长度
var slice1 []int
slice2 := []int {元素1[, 元素2, ...]}
b. 从数组(或者切片或者字符串)中获取 arr[i:j] i=数组的开始位置,j=结束位结果,j-i=切片的长度,i和j都可以省略,省略时 i=0, j=len(arr),i是从0开始,j是从1开始
a b c d e f
i 0 1 2 3 4 5
j 1 2 3 4 5 6
slice1 := arr[:] //arr[0:6]/arr[0:] slice2 := arr[1:1] //[] slice4 := arr3[1:3] //b c slice5 := arr3[:5] // = arr3[0:5]
c. make
slice1 := make([]int, 5, 10)
len(slice1) = 5, cap(slice1) = 10, 元素的初始值为0
2.2 相关函数
len(slice): 返回 slice 的元素个数(长度)
cap(slice): 返回 slice 的分配空间大小
append(slice1, slice2...): 把 slice2 追加到 slice1 产生新的 slice, 若 slice2 是变量时,不能省略...,相当于 append(slice1, a[, b, ...])
copy(目标slice, 源slice): 以最小的切片元素个数为准,将源 slice 复制到 目标 slice
2.3 cap - len = 0 时,系统将动态分配新的数组空间,即切片会自动处理存储空间不足的问题
2.4 遍历与 array 一样
2.5 在传递参数时,传递的为指针
3. map
在Java/python等语言中都有提供
暂时可以理解为:一张无序的表
其长度也不固定,也是引用类型,在赋值与传参过程中,指向同一地址
key1 value1
key2 value2
... ...
3.1 声明与创建
var map变量名 map[键type] 值type //键type可以为int或者string,值type,需要make初始化
map变量名 = make(map[键type] 值type)
//或者
map变量名 := make(map[键type] 值type) [{键1:值1}[,{键2:值2},...}] //[]中为可选
3.2 相关操作
赋值: map变量名[键] = 值
读取: map变量名[键] //如果键不存在,返回nil
删除键值对: delete(map变量名, 键) //如果键不存在,无影响
取map的元素个数: len(map变量名)
不能用cap函数
note_type_2.go code list
package main import "fmt" func main() { //先声明后赋值 var arr [3]int //arr = {1, 2, 3} //不能这样赋值给数组 arr[0] = 1 arr[1] = 2 arr[2] = 3 //arr[3] = 4 //compile error: index out of bounds fmt.Println(arr[0], arr[0:2]) //输出 1 [1 2] //arr1 := [3]int{4, 5, 6} arr1 := [...]int{4, 5, 6} //和上面结果一样 fmt.Printf("arr[1] = %d ", arr1[1]) //输出 arr[1] = 5 //遍历数组 for i := 0; i < len(arr); i++ { fmt.Printf("arr[%d] = %d ", i, arr[i]) } fmt.Println() for k, v := range arr1 { fmt.Printf("arr[%d] = %d ", k, v) } fmt.Println() changeValue(arr1) fmt.Println("result: ", arr1) //result: [4 5 6] 值不发生改变 //二维数组 arr2 := [2][3]int{{1, 2}, {4, 5, 6}} fmt.Println("len(arr2) = ", len(arr2)) //len(arr2) = 2 fmt.Println("len(arr2[0]) = ", len(arr2[0])) //len(arr2[0]) = 3 for i, v := range arr2 { fmt.Println(i, v) } for i1, v1 := range arr2 { for i2, v2 := range v1 { fmt.Printf("arr2[%d][%d] = %d ", i1, i2, v2) } fmt.Println() } //slice slice1 := []byte {'b', 'b'} slice1[0] = 'a' //如果只声明了slice,无元素时,直接通过下标赋值会compile error fmt.Printf("slice1[0] = %c ", slice1[0]) //slice1[0] = a arr3 := [...]byte {'a', 'b', 'c', 'd', 'e', 'f'} slice2 := arr3[:] // = arr3[0:] fmt.Println("slice2 = ", slice2) slice3 := arr3[1:1] //空 fmt.Println("slice3 = ", slice3) slice4 := arr3[1:3] //b c fmt.Println("slice4 = ", slice4) slice5 := arr3[:5] // = arr3[0:5] fmt.Println("slice5 = ", slice5) slice6 := slice5[1:2] //b fmt.Println("slice6 = ", slice6) str := "hello" slice7 := str[4:5] //o fmt.Printf("slice7[0] = %s ", slice7) //slice7[0] = o fmt.Println("len(slice4) = ", len(slice4)) //len(slice4) = 2 fmt.Println("cap(slice4) = ", cap(slice4)) //cap(slice4) = 5 //slice8 := append(slice4, 'a', 'd') //b c a d slice9 := []byte {'a', 'b'} slice8 := append(slice4, slice9...) //b c a d = append(slice4, 'a', 'b') fmt.Printf("slice8[2] = %c ", slice8[2]) //slice8[2] = a fmt.Println("len(slice8) = ", len(slice8)) //len(slice8) = 4 slice10 := []byte {'x', 'y', 'z'} copy(slice10, slice9) for i, v := range slice10 { fmt.Printf("slice10[%d] = %c ", i, v) //a b z } fmt.Println() /* //slice9 = a, b; slice10 = x, y,z copy(slice9, slice10) for i, v := range slice9 { fmt.Printf("slice9[%d] = %c ", i, v) //x y } */ s1 := make([]int, 5, 10) fmt.Println("len, cap = ", len(s1), ", ", cap(s1)) //len, cap = 5, 10 s2 := []int {1, 2, 3} changeValue2(s2) fmt.Println("result2: ", s2) //result2: [5 2 3] 结果会发生改变 //map var map1 map[string] string //map1["a"] = "123" //如果不初始化,会出现异常 panic: runtime error: assignment to entry in nil map map1 = make(map[string] string) map1["a"] = "123" fmt.Println("map1 = ", map1) //map1 = map[a:123] fmt.Println(map1["b"]) // (nil) b, found := map1["b"] //found 为 bool 值, true = found if found { fmt.Println("found, and the value = ", b) } else { fmt.Println("not found") } map1["b"] = "456" fmt.Println("map1 = ", map1) //map1 = map[a:123 b:456] delete(map1, "b") //删除键为"a"的键值对 fmt.Println("map1 = ", map1) //map1 = map[b:456] fmt.Println("len(map1) = ", len(map1)) //len(map1) = 1 //fmt.Println("cap(map1) = ", cap(map1)) // invalid argument map1 (type map[string]string) for cap map2 := map1 map2["a"] = "789" fmt.Println("map1 = ", map1) //map1 = map[a:789],其值为发生改变,因为map2和map1是同一地址空间 } func changeValue(arr [3]int) { arr[0] = 100 fmt.Println("changeValue: ", arr) //changeValue: [100 5 6] } func changeValue2(slc []int) { slc[0] = 5 fmt.Println("changeValue2: ", slc) //changeValue2: [5 2 3] }
运行结果: