阿坦
@37157522
聊一聊 Golang 的四大数据类型
Go 语言入门 Coding Golang
2022-04-27 15:18
Words count: 1523
Golang 的世界里,有最恶名昭彰,实力最强的 4 种数据类型。彼此之间处于竞争关系,但是各有各的特色。由此,各自有各自的生存空间。它们分别是数组、切片、映射、构建存储(struct)
本文首发于 PRSDigg(顶呱呱) © 2022 阿坦
转载请注明出处
原创不易,请多转发点赞

Golang 的世界里,有最恶名昭彰,实力最强的 4 种数据类型。彼此之间处于竞争关系,但是各有各的特色。由此,各自有各自的生存空间。

它们分别是数组、切片、映射、构建存储(struct)。

数组

// 数组变量声明
var array [5]int

可以看到,数组是一个集合,里面的值都是同一类型,同时,数组在声明的时候就已经限定了元素数量,本例为 5 个元素。有额外的元素想要添加到这个数组怎么办?没办法。这时,如果能有一种可以拓展元素数量的数组,有拓展需求的码农我想一定会很开心。于是,切片出现了……

切片

// 切片的声明
var mySlice []string

通过切片的声明语句,可以看到,切片变量不需要在声明时确定元素数量。也就是说,想给它添加几个元素就可以给它添加几个元素,切片在元素数量上可以更自由。

怎么实现的呢?

切片实际上是一个数组的一个片段。1

slice1

slice2

slice3

在声明切片时,内存里实际上先创建了一个数组,拿来给这个切片使用。

不是说数组是一种在声明时就确定了元素数量的东西吗?那当它里面的切片拓展超过了容纳它的数组规定的数量时,不就没法实现了吗?

答案是 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?

是因为未经赋值的 key 默认是零值,而布尔值的零值是 false

有没有留意到 nilMap["dance"] 的值也等于 false?

nilMap["dance"] = false,nilMap["swim"] = false,区别在于 nilMap["dance"] 这个 false 是我赋给它的,而 nilMap["swim"] 的 false 是默认的。

问题来了,我怎么知道一个 key 当前赋值了没有?

当我们访问一个映射的特定 key 时,会返回两个值:

  • 第一个是当前 key 对应的值;

  • 第二个是一个布尔值,表示它在声明后有没有被赋值:

    • true 就是已经赋值了;
    • false 就是还没有赋值。
_, ok1 := nilMap["dance"]
_, ok2 := nilMap["swim"]
fmt.Println(ok1, ok2) // 结果: true false

nilMap["dance"] 被赋值了,nilMap["swim"] 还没有,原来是这个意思。

你捋清楚了吗?哪里不清楚欢迎留言告诉我!

构建存储(struct)

一个数组只能存储一种类型的值(切片也一样);

一个映射里所有的 key 是同一种类型,所有的 value 是同一种类型。

我想把不同类型的值存到一个容器里,有办法吗?

构建存储(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}

代码解析:

用关键字 type 开头,定义好 struct 要设定一些什么 key, 每个 key 分别保存什么类型的值,把这种构建类型称为 subscriber。

之后,在声明变量时,就可以用 subscriber 来确定变量的类型,subscriber 和 int, string, bool, float64 一样使用。

通过代码可以看到,订阅者 1 号 subscriber1 经过构建类型 subscriber 的塑造,成功地同时保存了字符串、浮点数、布尔值。

小结

和打架一个道理,直拳打不着试试摆拳,摆拳不行试试勾拳。

数组不适合考虑下切片,切片不适合考虑下映射(map),映射不适合考虑下构建(struct)。

四大数据类型让你的代码更“能打”。

  1. Jay, McGavren. Head First Go. China Machine Press, 2020. ↩

Arweave TX
5TjMxp39rfch6Qt1noUO21qzGm0rouIIRY0TSlEv5lI
Content Digest
241469ad3f478bb8e63d28df08879f69d209932101122aa172350999a8a50705
Reward
3 : 0
0 times bought, 0 times reward
0.0
Price(BTC)
0
Paid Times
0.0
Revenue(USD)
0.0
My Share(%)
Comments
Subscribe
阿坦
@37157522
Subscribing: 45 Subscribers: 117
潮起潮落是什么都不为
Subscribe
Related Posts
关于 John Arundel 的 Go 学习建议,我做到了哪些? Go 语言学习——寂静 Go 语言学习——吃好 Go 语言学习——学东西 Go 语言学习——做个计划
Rules Stats Help Github Twitter Discord
阿坦
@37157522
Subscribing: 45 Subscribers: 117
潮起潮落是什么都不为
Subscribe
Related Posts
关于 John Arundel 的 Go 学习建议,我做到了哪些? Go 语言学习——寂静 Go 语言学习——吃好 Go 语言学习——学东西 Go 语言学习——做个计划
Rules Stats Help Github Twitter Discord