数组
Go语⾔当中,可以将⼀组类型相同的数据存放在⼀个数组当中,数组中元素的类型可以是Go语⾔原⽣
类型,也可以是⾃定义类型(struct)。声明⽅式可以参考变量:
var variable_name [SIZE] variable_type
var sa [10] int64 //定义⼀个10个int64类型的数组
var ss [3] string = [3]string{"lily","lucy","lilei"}//定义3个⻓度的字符数组
package main
import "fmt"
func main() {
// 定义5个元素的整型数组
var five [5]int = [5]int{1,2,3,4,5}
// 定义3个元素的字符串数组
var three [3]string=[3]string{"zhangsan","lisi","wangwu"}
fmt.Println(five)
fmt.Println(three)
}
结果
[1 2 3 4 5]
[zhangsan lisi wangwu]
注意:数组是固定⻓度的,不可以越界!
在Go语⾔当中,同样可以定义⼆维数组
package main
import (
"fmt"
)
func main() {
//Go语⾔当中的⼆维数组,可以理解为3⾏4列
a2 := [3][4]int{
{0, 1, 2, 3}, /* 第⼀⾏索引为 0 */
{4, 5, 6, 7}, /* 第⼆⾏索引为 1 */
{8, 9, 10, 11}, /* 第三⾏索引为 2 */
}
//注意上述数组初始化的逗号
fmt.Println(a2)
//如何遍历该数组?可以写2层for循环搞定
for i := 0; i < 3; i++ {
for j := 0; j < 4; j++ {
fmt.Printf("i = %d, j = %d, val = %d\n", i, j, a2[i][j])
}
}
}
结果
[[0 1 2 3] [4 5 6 7] [8 9 10 11]]
i = 0, j = 0, val = 0
i = 0, j = 1, val = 1
i = 0, j = 2, val = 2
i = 0, j = 3, val = 3
i = 1, j = 0, val = 4
i = 1, j = 1, val = 5
i = 1, j = 2, val = 6
i = 1, j = 3, val = 7
i = 2, j = 0, val = 8
i = 2, j = 1, val = 9
i = 2, j = 2, val = 10
i = 2, j = 3, val = 11
切⽚
由于数组是固定⼤⼩的,这在使⽤上缺少⼀定便利,因此Go语⾔⼜提供了切⽚类型,乍⼀看切⽚与数组
没有区别,只不过它的⼤⼩是可以扩充的,也就是说可以把切⽚理解成动态数组,⾄于为什么叫切⽚,
可以脑补⼀下⾯包⽚(⻓⾯包想象成⼀个数组,切⽚是从其某段切下来)。
切⽚中有2个概念:⻓度和容量
- ⻓度 指被赋过值的最⼤下标+1
- 容量 指切⽚能容纳的最多元素个数
其实内部还有一个数据指针来指向这些数据的空间地址
切⽚可以⽤array|slice[start:end]的⽅式进⾏截取,得到新的切⽚,其中start和end代表下标位置,都
可以省略,start省略代表从头开始,end省略代表直到末尾。
package main
import (
"fmt"
)
func main() {
a1 := [5]int{1, 2, 3, 4, 5} // a1 是⼀个数组
fmt.Println(a1)
s1 := a1[2:4] //定义⼀个切⽚
fmt.Println(s1)
s1[1] = 100 //切⽚下标不能超过
fmt.Println("after---切片修改会影响原数组")
fmt.Println(a1)
fmt.Println(s1)
}
结果
[1 2 3 4 5]
[3 4]
after---切片修改会影响原数组
[1 2 3 100 5]
[3 100]
通过上述例⼦,我们可以得出2个知识点:
- 切⽚start:end是前闭后开,也就是实际截取下标是start到end-1
- 切⽚是引⽤类型,对切⽚的修改会影响对应的数组
与切⽚相关的内建函数:
len(s)
- 计算切⽚容量.
cap(s)
- append 向切⽚追加元素
var s1 []T
append(s1,T)
- make 可以创建切⽚
make([]T, length, capacity) //capacity 可以省略,默认与len⼀致
- copy 复制切⽚
copy(s2,s1) //将s1内容拷⻉到s2,此时s1与s2是独⽴的,修改互不⼲预
package main
import "fmt"
func main() {
var s1 []int //定义切⽚s1
s1 = append(s1, 1) //追加,注意s1必须接收追加结果
s1 = append(s1, 2)
s1 = append(s1, 3, 4, 5) //可以⼀次追加多个
printSlice(s1)
s2 := make([]int, 3)
printSlice(s2)
s2 = append(s2, 4) //当超过容量的时候,容量会以len*2的⽅式⾃动扩⼤
printSlice(s2)
copy(s1,s2)
printSlice(s1)
s2[0]=1000
printSlice(s2)
}
func printSlice(s []int) {
fmt.Printf("len = %d, cap = %d, s = %v\n", len(s), cap(s), s)
}
结果
len = 5, cap = 6, s = [1 2 3 4 5]
len = 3, cap = 3, s = [0 0 0]
len = 4, cap = 6, s = [0 0 0 4]
len = 5, cap = 6, s = [0 0 0 4 5]
len = 4, cap = 6, s = [1000 0 0 4]
当切⽚容量不够时,追加不会报错,⽽会扩⼤容量,扩⼤容量默认采⽤len*2
的数据。根据多个例⼦编写,Go语⾔默认都会对变量进⾏初始化,这⼀点很友好!
map(键值对)
Go语⾔同样提供了map这样的容器,map可以存放⽆序的键值对,map是⼀种集合,但注意它是⽆序
的。map需要使⽤make来构造,否则它是⼀个nil-map,⽆法存放键值对。
var map_variable map[key_data_type]value_data_type
map_variable = make(map[key_data_type]value_data_type)
或
map_variable := make(map[key_data_type]value_data_type)
package main
import "fmt"
func main() {
countryCapitalMap := make(map[string]string)
// map插⼊key - value对,各个国家对应的⾸都
countryCapitalMap["France"] = "Paris"
countryCapitalMap["Italy"] = "Roma"
countryCapitalMap["China"] = "BeiJing"
countryCapitalMap["India "] = "New Delhi"
fmt.Println(countryCapitalMap["China"])
//当key不存在时,直接打印不太优雅,可以使⽤下⾯的⽅法
val, ok := countryCapitalMap["Japan"]
if ok {
fmt.Println("Japan's capital is", val)
} else {
fmt.Println("Japan's capital not in map")
}
}
结果
BeiJing
Japan's capital not in map
在取map的值时可以⽤⼀个变量接收,也可以增加⼀个指示变量,来判断key值是否真实存在。下⾯还
有⼀个问题,如何对map进⾏遍历呢?这需要⽤到range关键字,它可以让我们优雅的遍历Go语⾔各种
容器,当然包括map。具体⽤法可以看代码:
package main
import "fmt"
func main() {
countryCapitalMap := make(map[string]string)
// map插⼊key - value对,各个国家对应的⾸都
countryCapitalMap["France"] = "Paris"
countryCapitalMap["Italy"] = "Roma"
countryCapitalMap["China"] = "BeiJing"
countryCapitalMap["India "] = "New Delhi"
//遍历map
for k, v := range countryCapitalMap {
fmt.Println(k, "'s capital is", v) //k,v分别是map的key和val
}
//遍历数组,如果不想获得
a := []int{10, 20, 30, 40, 50}
for k, v := range a {
fmt.Printf("a[%d]=%d\n", k, v) //k代表数组下标,v代表该元素值
}
}
结果
France 's capital is Paris
Italy 's capital is Roma
China 's capital is BeiJing
India 's capital is New Delhi
a[0]=10
a[1]=20
a[2]=30
a[3]=40
a[4]=50
如果不想获得k或v的值时,可以⽤_占位,这个语法在其他多变量赋值时同样适⽤。
_, v := range countryCapitalMap //只取v的值