数组声明
朴素的方法
//var arr_name[quality]Type
var arr[4]int
数组内元素赋值
//arr_name[index] = Value
arr[0] = 5
已知数组值时的方法
//第一种:指定长度
//var arr = [len]type{value1, value2, ...}
var arr1 = [5]int{18, 20, 15, 22, 16}
var arr2 = [10]int{1, 1, 1}//除了前三个剩下全部自动赋0
//第二种:不指定长度,长度取决于初始化元素个数
//var arr = [...]type{value1, value2, ...}
var arr = [...]int{18, 20, 15, 22, 16}//[5]int
//第三种:只给特定索引赋值
//var arr = [len]type{key1:value1, key2:value2, ...}
var arr = [5]string{3: "Chris", 4: "Ron"}
多维数组
//var matrix [x_len][y_len]type
var matrix [5][3]int
切片
内部实现
朴素声明
//var slice_name[]Type
var slice[]int
声明切片和数组的区别仅仅是去掉了中括号中的元素个数!
由已知数组而来
//var slice []type = arr[start: end]
//取arr[start, end)区间里的元素
var slice []type = arr[:]//切片取arr全部元素
var slice []type = arr[:5]//切片取arr[0, 5)
var slice []type = arr[3:]//切片取arr[3, len(arr))
make函数声明
slice := make([]string, 5)
这种方法创建了一个容量和长度都是5的字符串切片.
slice := make([]string, 3, 5)
这种方法创建了一个容量为5,长度为3的字符串切片.
append()函数
在Go语言中,为切片“扩充”需要使用append()函数,使用格式如下:
//append(s []T, x ...T)
append(slice, 1)
append()函数本身并不改变原有切片,只是将切片扩容后的结果作为返回值.因此,需要将“扩容”后的结果再次
(即函数返回值)赋值给slice_name,才能真正使slice_name发生改变.
slice = append(slice, value)
append()常见用法如下:
a = append(a, b...) //将切片b的元素追加到切片a之后
b = make([]T, len(a))
copy(b, a)
//复制切片a的元素到新的切片b上
a = append(a[:i], a[i+1:]...)//切除切片a中位于索引i的元素
a = append(a[:i], a[j:]...)//切除切片a中从索引i至j位置的元素
a = append(a, make([]T, j)...)//为切片a扩展j个元素长度
a = append(a[:i], append([]T{x}, a[i:]...)...)//在索引i的位置插入元素x
a = append(a[:i], append(make([]T, j), a[i:]...)...)//在索引i的位置插入长度为j的新切片
a = append(a[:i], append(b, a[i:]...)...)//在索引i的位置插入切片b的所有元素
x, a = a[len(a) - 1], a[: len(a) - 1]//取出位于切片a最末尾的元素x
copy()函数
//func copy(dst, src []T) int
- 若 len(dst) \geqslant len(src) ,则 src 切片会将其所有 n 个元素赋给 dst 的前 n 个位置
- 若 len(dst) < len(src) ,则 src 切片会将其前 len(dst) 个元素赋给 dst
返回值是 \min\{len(dst), len(src)\} .
可以利用copy()函数实现对切片的各种操作:
切片扩容:将切片的长度扩充为原来的若干倍
func magnify(s []int, factor int) []int {
newSlice := make([]int, len(s)*factor)
copy(newSlice, s)
s = newSlice
return s
}
切片间互相插入:将一个切片插入到另一个切片的指定位置
func InsertStringSlice(slice, insertion []string, index int) []string {
result := make([]string, len(slice)+len(insertion))
at := copy(result, slice[:index])
at += copy(result[at:], insertion)
//借助切片result[at:]和result底层指向同一数组来修改result切片
copy(result[at:], slice[index:])
return result
}
删除部分切片:
func RemoveStringSlice(slice []string, start, end int) []string {
result := make([]string, len(slice)-(end-start))
at := copy(result, slice[:start])
copy(result[at:], slice[end:])
//借助切片result[at:]和result底层指向同一数组来修改result切片
return result
}
集合
集合初始化
集合(map)可以看作是一类特殊的切片,只不过集合的元素都是由若干“键-值对”数据构成的.
//var map_name = make(map[key_type]value_type)
var studentInfos = make(map[string]string)
key_type表示键的类型,value_type表示值的类型.
注意:不要使用new()来初始化集合!否则会获得一个空引用的指针.
studentInfos["0001"] = "王小红"
集合中元素的赋值和数组类似,只不过中括号中不再是索引,而是键的值.
一次性打印集合结果
package main
import "fmt"
func main() {
playerInfo := make(map[string]string)
playerInfo["Doinb"] = "大币老师"
playerInfo["scout"] = "小飞"
playerInfo["scout"] = "小飞"
fmt.Println(playerInfo)
}
打印集合的结果如下
map[Doinb:大币老师 scout:小飞]
\boxed{和python一样,集合可以用来去重} .
用map实现分支结构
map的key不能是数组、切片和结构体类型的,但value可以是任意类型的,甚至可以是函数类型.
示例如下:
package main
import "fmt"
func main() {
mf := map[int]func() int{
1: func() int { return 10 },
2: func() int { return 20 },
5: func() int { return 50 },
}
fmt.Println(mf)
}
//输出map[1:0x10903be0 5:0x10903ba0 2:0x10903bc0]
用切片作为map的值来实现隐函数
mp1 := make(map[int][]int)
mp2 := make(map[int]*[]int)
测试键值对是否存在
当用map[key]的方式来获取对应的值时,若map中不存在key,则会返回value类型的空值,导致无法判断究竟是没有key还是key对应的value就是空值,故需要以下方法:
_, ok := map1[key1] // 如果key1存在则ok == true,否则ok为false
删除键值
delete(map1, key1)
即使key1不存在,该操作也不会产生错误.
len()函数
数组/指向数组的指针/切片/集合均可作为len()函数的参数,返回参数的元素个数.
for-range结构
除了for循环外,Go语言还提供了range关键字,与for结合,也可以实现循环遍历.(遍历集合非常好用)
/*
for index, value := range variable {
// 循环体
}
*/
for key, value := range studentInfos {
fmt.Println("学号:", key, "姓名:", value)
}
其中,index表示索引或键的值;value表示元素的值;variable表示数组、切片或集合变量;由大括号包裹的部分
是循环体,可以使用index和value变量.
示例:
package main
import "fmt"
func main() {
playerInfo := make(map[string]string)
playerInfo["Doinb"] = "大币老师"
playerInfo["scout"] = "小飞"
for id, nickname := range playerInfo {
fmt.Println("id:", id, "外号:", nickname)
}
}
输出:
id: Doinb 外号: 大币老师
id: scout 外号: 小飞
\boxed{这种结构适用于集合/切片/数组.}