Go基础|第9章:map

  • 原创
  • Madman
  • /
  • /
  • 0
  • 1844 次阅读

Golang.jpg

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 增、删、改、查

对映射类型的键值对进行增、删、改是常量时间!

新增键值对:

m := make(map[string]int)
m["golang"] = 100
m["python"] = 90

判断键是否存在: 如果键存在,则 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

所以推荐的做法是先判断键存不存在:

if v, ok := m["shell"]; ok {
    fmt.Println(v)
}

删除指定键值对,即使键不存在也是安全的:

delete(m, "golang")
delete(m, "shell")

1.3 迭代

键值对出现的顺序是不固定的。从 Go 1.12 版本开始,用 fmt 包(比如 fmt.Printf)来打印映射的内容时,默认已经按键排序了!

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
*/
分类: Go Basic
标签: map make() golang
未经允许不得转载: LIFE & SHARE - 王颜公子 » Go基础|第9章:map

分享

作者

作者头像

Madman

如需 Linux / Python 相关问题付费解答,请按如下方式联系我

0 条评论

暂时还没有评论.