Golang 的世界里,有最恶名昭彰,实力最强的 4 种数据类型。彼此之间处于竞争关系,但是各有各的特色。由此,各自有各自的生存空间。
它们分别是数组、切片、映射、构建存储(struct)。
数组
// 数组变量声明
var array [5]int
可以看到,数组是一个集合,里面的值都是同一类型,同时,数组在声明的时候就已经限定了元素数量,本例为 5 个元素。有额外的元素想要添加到这个数组怎么办?没办法。这时,如果能有一种可以拓展元素数量的数组,有拓展需求的码农我想一定会很开心。于是,切片出现了……
切片
// 切片的声明
var mySlice []string
通过切片的声明语句,可以看到,切片变量不需要在声明时确定元素数量。也就是说,想给它添加几个元素就可以给它添加几个元素,切片在元素数量上可以更自由。
怎么实现的呢?
切片实际上是一个数组的一个片段。[1]
在声明切片时,内存里实际上先创建了一个数组,拿来给这个切片使用。
不是说数组是一种在声明时就确定了元素数量的东西吗?那当它里面的切片拓展超过了容纳它的数组规定的数量时,不就没法实现了吗?
答案是 No
数组和切片的关系可以这么理解:数组是切片的宿主。
切片想要自由扩张,当它的宿主(数组)容量不够时,它就换一个容量更大的数组。切片接着扩张,宿主容量又不够了,换更大的数组。如此往复……
映射(map)
// 映射的声明
var nilMap map[string]bool
nilMap = make(map[string]bool)
nilMap["guitar"] = true
nilMap["dance"] = false
数组、切片都是由索引和值构成。在数组创建时,索引就自动添加好了,从 0 开始递增,每个索引对应一个元素。
key
以前面示例中的映射声明打印出来就是这个样子:
map[dance:false guitar:true]
nilMap["swim"]fmt.Println(nilMap["swim"])false
nilMap["swim"]false
keyfalse
nilMap["dance"]false
nilMap["dance"] = falsenilMap["swim"] = falsenilMap["dance"]falsenilMap["swim"]false
问题来了,我怎么知道一个 `key` 当前赋值了没有?
key
keytruefalse
_, ok1 := nilMap["dance"]
_, ok2 := nilMap["swim"]
fmt.Println(ok1, ok2) // 结果: true false
nilMap["dance"]nilMap["swim"]
你捋清楚了吗?哪里不清楚欢迎留言告诉我!
构建存储(struct)
一个数组只能存储一种类型的值(切片也一样);
keyvalue
我想把不同类型的值存到一个容器里,有办法吗?
构建存储(struct) 应运而生:
package main
import "fmt"
type subscriber struct {
name string
rate float64
active bool
}
func main() {
var subscriber1 subscriber
subscriber1.name = "Aman Singh"
subscriber1.rate = 5.99
subscriber1.active = true
fmt.Println(subscriber1)
}
// 结果:{Aman Singh 5.99 true}
typestructkeykeysubscriber
subscribersubscriberintstringboolfloat64
subscriber1subscriber
小结
和打架一个道理,直拳打不着试试摆拳,摆拳不行试试勾拳。
数组不适合考虑下切片,切片不适合考虑下映射(map),映射不适合考虑下构建(struct)。
四大数据类型让你的代码更“能打”。
[1]: Jay, McGavren. Head First Go. China Machine Press, 2020.