Go基础|第9章:map
Synopsis: Go 语言里用映射用来处理具有键值对结构的数据,可以使用 map literal 或 make 函数来初始化映射。注意映射的零值为 nil,不能给它添加键值对,否则会报编译错误
1. 基础概念
映射(map)
也被称为字典,可用来存储一系列 无序的键值对,无序的原因是映射的实现使用了散列表。它的 每个键必须唯一,只能是支持相等性判断的类型,由于 function、slice、map 类型的值并不支持相等性判断,所以映射的键类型不能是这些类型
除了上述三种类型外,映射的键类型可以是数值型、string、pointer、interface、struct 或 array。另外,如果映射的键类型是 interface 时,那么接口值的具体类型不能是 function、slice、map,所以最好不要把映射的键类型设定为任何接口类型。如果映射的键类型是 array,那么还要确保 array 的元素类型不是 function、slice、map
映射的值可以是任何类型,比如切片 map[int][]string
与切片一样,映射也是引用类型。若将映射传入函数中,并更改了该映射的内容,则此修改对函数的调用者同样可见
1.1 声明与初始化
(1) 映射字面量
可以使用 map literal
来初始化一个映射类型的值:
package main import "fmt" func main() { m := map[string]int{ "golang": 100, "python": 90, } //m := map[string]int{} // Empty map of string-int pairs fmt.Printf("%#v\n", m) // map[string]int{"golang":100, "python":90} }
(2) make() 函数创建映射
package main import "fmt" func main() { m := make(map[string]int) // Empty map of string-int pairs //m := make(map[string]int, 10) // Preallocate room for 10 entries m["golang"] = 100 m["python"] = 90 fmt.Printf("%#v\n", m) // map[string]int{"golang":100, "python":90} }
注意:映射类型的零值(zero value)是
nil
,它和空映射的唯一区别是它不能新增键值对
,除此以外,我们对一个值为 nil 的映射做任何操作都不会引发错误:
var m map[string]int // nil map of string-int pairs m["golang"] = 100 // panic: assignment to entry in nil map
用内置函数 len()
可以获取映射的大小,即键值对的数目
1.2 增、删、改、查
对映射类型的键值对进行增、删、改是常量时间!
新增键值对:
判断键是否存在:如果键存在,则 v 是它的值、ok 是 true; 如果键不存在,则 v 是值对应的类型的零值、ok 是 false:
v, ok := m["golang"] fmt.Println(v, ok) // 100 true v, ok = m["shell"] fmt.Println(v, ok) // 0 false
所以推荐的做法是先判断键存不存在:
删除指定键值对,即使键不存在也是安全的:
1.3 迭代
键值对出现的顺序是不固定的
package main import "fmt" func main() { m := map[string]int{ "golang": 100, "python": 90, "shell": 80, "node.js": 85, } fmt.Printf("%#v\n", m) // map[string]int{"golang":100, "python":90} for key, value := range m { fmt.Printf("Key: %v, value: %v\n", key, value) } } /* Output: map[string]int{"golang":100, "node.js":85, "python":90, "shell":80} Key: shell, value: 80 Key: node.js, value: 85 Key: golang, value: 100 Key: python, value: 90 */
2. 在函数间传递映射
当传递映射给一个函数,并对这个映射做了修改时,所有对这个映射的引用都会察觉到这个修改:
package main import ( "fmt" ) func remove(m map[string]int, key string) { delete(m, key) } func main() { m := map[string]int{ "golang": 100, "python": 90, "shell": 80, "node.js": 85, } for key, value := range m { fmt.Printf("Key: %v, value: %v\n", key, value) } remove(m, "python") fmt.Println() for key, value := range m { fmt.Printf("Key: %v, value: %v\n", key, value) } } /* Output: Key: golang, value: 100 Key: python, value: 90 Key: shell, value: 80 Key: node.js, value: 85 Key: golang, value: 100 Key: shell, value: 80 Key: node.js, value: 85 */
3. 获取键或值的切片
package main import "fmt" func main() { m := map[string]int{ "golang": 100, "python": 90, "shell": 80, "node.js": 85, } keys := make([]string, 0, len(m)) values := make([]int, 0, len(m)) for k, v := range m { keys = append(keys, k) values = append(values, v) } fmt.Printf("%v len=%d cap=%d\n", keys, len(keys), cap(keys)) // [golang python shell node.js] len=4 cap=4 fmt.Printf("%v len=%d cap=%d\n", values, len(values), cap(values)) // [100 90 80 85] len=4 cap=4 }
4. 通过键排序映射
package main import ( "fmt" "sort" ) func main() { m := map[string]int{ "golang": 100, "python": 90, "shell": 80, "node.js": 85, } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } fmt.Printf("%v len=%d cap=%d\n", keys, len(keys), cap(keys)) // [golang python shell node.js] len=4 cap=4 sort.Strings(keys) fmt.Printf("%v len=%d cap=%d\n", keys, len(keys), cap(keys)) // [golang node.js python shell] len=4 cap=4 for _, k := range keys { fmt.Printf("Key: %v, value: %v\n", k, m[k]) } } /* Output: [golang python shell node.js] len=4 cap=4 [golang node.js python shell] len=4 cap=4 Key: golang, value: 100 Key: node.js, value: 85 Key: python, value: 90 Key: shell, value: 80 */
0 条评论
评论者的用户名
评论时间暂时还没有评论.