Go语言中的Array、Slice、Map和Set使用详解

2019-11-10 08:57:44于海丽

使用字面值是创建 map 惯用的方法(为什么不使用make)。初始化 map 的长度依赖于键值对的数量。

map 的键可以是任意内建类型或者是 struct 类型,map 的值可以是使用 ==操作符的表达式。slice,function 和 包含 slice 的 struct 类型不可以作为 map 的键,否则会编译错误:

dict := map[[]string]int{}

Compiler Exception:
invalid map key type []string

使用 map

给 map 赋值就是指定合法类型的键,然后把值赋给键:

colors := map[string]string{}
colors["Red"] = "#da1337"

如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对,否则会报运行时错误:


var colors map[string]string
colors["Red"] = "#da1337"

Runtime Error:
panic: runtime error: assignment to entry in nil map

测试 map 的键是否存在是 map 操作的重要部分,因为它可以让我们判断是否可以执行一个操作,或者是往 map 里缓存一个值。它也可以被用来比较两个 map 的键值对是否匹配或者缺失。

从 map 里检索一个值有两种选择,我们可以同时检索值并且判断键是否存在:

value, exists := colors["Blue"]
if exists {
  fmt.Println(value)
}

另一种选择是只返回值,然后判断是否是零值来确定键是否存在。但是只有你确定零值是非法值的时候这招才管用:

value := colors["Blue"]
if value != "" {
  fmt.Println(value)
}

当索引一个 map 取值时它总是会返回一个值,即使键不存在。上面的例子就返回了对应类型的零值。

迭代一个 map 和迭代数组和 slice 是一样的,使用 range 关键字,不过在迭代 map 时我们不使用 index/value 而使用 key/value 结构:

colors := map[string]string{
    "AliceBlue":   "#f0f8ff",
    "Coral":       "#ff7F50",
    "DarkGray":    "#a9a9a9",
    "ForestGreen": "#228b22",
}

for key, value := range colors {
  fmt.Printf("Key: %s  Value: %sn", key, value)
}

如果我们想要从 map 中移除一个键值对,使用内建函数 delete(要是也能返回移除是否成功就好了,哎。。。):


delete(colors, "Coral")

for key, value := range colors {
  fmt.Println("Key: %s  Value: %sn", key, value)
}

在函数间传递 map

在函数间传递 map 不是传递 map 的拷贝。所以如果我们在函数中改变了 map,那么所有引用 map 的地方都会改变:


func main() {
  colors := map[string]string{