map是go内置类型,使用key关联value
特点
- map是无序的, 每次打印出来的map都会不一样,不能通过index获取,必须通过key获取
- 长度是不固定的,也slice一样,是引用类型
- 内置的len同样适用于map,返回map拥有的key数量
- key可以是比较的类型:布尔、整数、浮点、复杂型、字符串型
使用
有三种定义方式:
var map_variablemake(map[key_dta_type]value_data_type)rating := map[string]float32{"C": 5, "GO": 4.5, "Python": 4.5}
map没有初始化的话, 是 nil map,不能用来存放键值对
即:
- nil map == map[kType]vType(nil)
- 初始化 == 分配内存
创建
检查
获取key对应的 value,
map[key]
但是当 key 如果不存在时,我们会得到该 vlaue值顾炎武的默认值(零值),比如string是空字符串, int是0,但是程序不会报错。
所以我们可以使用 ok-idiom 获取值,可知道 key/value是否存在
value, ok :=`map[key]
修改
map[1] = "xxx"
删除
func delete(m map[Type]Type1, key Type)
delete内置函数从映射中删除具有指定键(m[key])的元素。如果m是nil,或者不存在这样的元素,则delete是no-op。
遍历
for range
map1 := make(map[int]string)map1[1] = "honhaier"map1[2] = "baigujing"for k, v range map1 {fmt.Println(k, v)}
如何有序的遍历 map
取出 key,排序后, 再输出 对应的vlaue
keys := make[]int, 0, len(map1)fmt.Println(keys)for k, _ := range map1 {keys = append(keys, k)}fmt.Println(keys)sort.Ints(keys) // 根据 int 排序fmt.Println(kyes)for _, key := range keys {fmt.Println(key, map1[key])}# 按字符排序s1 := []stirng{"Apple", "Window", "Orange", "abc", "隔壁老王", "acd"}fmt.Println(s1)sort.Strings(s1) // 按字符排序fmt.Println(s1)
结合slice
map结合slice使用
/** @Author: fuzhong* @LastEditTime: 2019-10-30 17:25:03*/package mainimport "fmt"func main() {map1 := make(map[string]string)map1["name"] = "隔壁老王"map1["age"] = "30"map1["sex"] = "男性"map1["address"] = "深圳xx区xx路"fmt.Println(map1) // map[address:深圳xx区xx路 age:30 name:隔壁老王 sex:男性]map2 := make(map[string]string)map2["name"] = "小明"map2["age"] = "22"map2["sex"] = "女性"map2["address"] = "上海xx区xx路"fmt.Println(map2)map3 := map[string]string{"name": "ruby", "age": "33", "sex": "男性", "address": "深圳宝安西乡"}fmt.Println(map3)}
并发
- read-only 线程安全
- RW 线程不安全
func main() {fmt.Println("并发读写map")m := make(map[int]int)go func() {for {m[1] = 1}}()go func() {for {_ = m[1]}}()for {}}/*outputD:\projects\go\demo>go run main.goHello world!并发读写mapfatal error: concurrent map read and map write // errorgoroutine 7 [running]:runtime.throw(0x4d3782, 0x21)D:/go/src/runtime/panic.go:1116 +0x79 fp=0xc00003df80 sp=0xc00003df50 pc=0x432889runtime.mapaccess1_fast64(0x4b3c40, 0xc00006a330, 0x1, 0xc000086048)D:/go/src/runtime/map_fast64.go:21 +0x19d fp=0xc00003dfa8 sp=0xc00003df80 pc=0x40ff7dmain.main.func2(0xc00006a330)D:/projects/go/demo/main.go:68 +0x47 fp=0xc00003dfd8 sp=0xc00003dfa8 pc=0x49e3e7runtime.goexit()D:/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc00003dfe0 sp=0xc00003dfd8 pc=0x45d241created by main.mainD:/projects/go/demo/main.go:66 +0x125goroutine 1 [runnable]:main.main()D:/projects/go/demo/main.go:72 +0x126goroutine 6 [runnable]:main.main.func1(0xc00006a330)D:/projects/go/demo/main.go:62 +0x47created by main.mainD:/projects/go/demo/main.go:60 +0x103exit status 2*/
并发读写需求,可以使用 sync.Map
type Map struct {mu Mutex// read contains the portion of the map's contents that are safe for// concurrent access (with or without mu held).//// The read field itself is always safe to load, but must only be stored with// mu held.//// Entries stored in read may be updated concurrently without mu, but updating// a previously-expunged entry requires that the entry be copied to the dirty// map and unexpunged with mu held.read atomic.Value // readOnly// dirty contains the portion of the map's contents that require mu to be// held. To ensure that the dirty map can be promoted to the read map quickly,// it also includes all of the non-expunged entries in the read map.//// Expunged entries are not stored in the dirty map. An expunged entry in the// clean map must be unexpunged and added to the dirty map before a new value// can be stored to it.//// If the dirty map is nil, the next write to the map will initialize it by// making a shallow copy of the clean map, omitting stale entries.dirty map[interface{}]*entry// misses counts the number of loads since the read map was last updated that// needed to lock mu to determine whether the key was present.//// Once enough misses have occurred to cover the cost of copying the dirty// map, the dirty map will be promoted to the read map (in the unamended// state) and the next store to the map will make a new dirty copy.misses int}
使用
n := sync.Map{}n.Store("a", 111)n.Store("b", 222)// fmt.Println(n)fmt.Printf("%#v", n)
