map是go内置类型,使用key关联value
特点
- map是无序的, 每次打印出来的map都会不一样,不能通过index获取,必须通过key获取
- 长度是不固定的,也slice一样,是引用类型
- 内置的len同样适用于map,返回map拥有的key数量
- key可以是比较的类型:布尔、整数、浮点、复杂型、字符串型
使用
有三种定义方式:
var map_variable
make(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 main
import "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 {
}
}
/*
output
D:\projects\go\demo>go run main.go
Hello world!
并发读写map
fatal error: concurrent map read and map write // error
goroutine 7 [running]:
runtime.throw(0x4d3782, 0x21)
D:/go/src/runtime/panic.go:1116 +0x79 fp=0xc00003df80 sp=0xc00003df50 pc=0x432889
runtime.mapaccess1_fast64(0x4b3c40, 0xc00006a330, 0x1, 0xc000086048)
D:/go/src/runtime/map_fast64.go:21 +0x19d fp=0xc00003dfa8 sp=0xc00003df80 pc=0x40ff7d
main.main.func2(0xc00006a330)
D:/projects/go/demo/main.go:68 +0x47 fp=0xc00003dfd8 sp=0xc00003dfa8 pc=0x49e3e7
runtime.goexit()
D:/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc00003dfe0 sp=0xc00003dfd8 pc=0x45d241
created by main.main
D:/projects/go/demo/main.go:66 +0x125
goroutine 1 [runnable]:
main.main()
D:/projects/go/demo/main.go:72 +0x126
goroutine 6 [runnable]:
main.main.func1(0xc00006a330)
D:/projects/go/demo/main.go:62 +0x47
created by main.main
D:/projects/go/demo/main.go:60 +0x103
exit 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)