A few points to note about using map
- 2020-11-03 22:24:01
- OfStack
1. Introduction
map is a convenient and powerful built-in data structure in Golang, an unordered group of elements of the same type, indexed by a unique key of the other type. Its keys can be any type supported by equality operators, such as integers, floating point Numbers, complex Numbers, strings, Pointers, interfaces (as long as their dynamic types support equality judgment), structures, and arrays. Slices cannot be used as mapping keys because their equality has not been defined. Like slice 1, the mapping is also a reference type. If you pass a map into a function and change the contents of that map, the change is also visible to callers. The uninitialized mapping value is nil.
Use examples are as follows:
package main
import "fmt"
func main() {
nameAge := make(map[string]int)
nameAge["bob"] = 18 // increase
nameAge["tom"] = 16 // increase
delete(nameAge, "bob") // delete
nameAge["tom"] = 19 // change
v := nameAge["tom"] // check
fmt.Println("v=",v)
v, ok := nameAge["tom"] // Look it up. Recommended usage
if ok {
fmt.Println("v=",v,"ok=",ok)
}
for k, v :=range nameAge { // traverse
fmt.Println(k, v)
}
}
Output results:
[
v= 19
v= 19 ok= true
tom 19
2. Notes
2.1 Elements of map are not addressable
The element in map is not a variable, but a value. Therefore, we cannot address elements of map.
var m = map[int]int {
0 : 0,
1: 1,
}
func main() {
fmt.Println(&m[0])
}
Operation error:
[cannot take the address of m[0]
]Therefore, when map's elements are struct type values, field values in the struct cannot be directly modified. Consider the following example:
package main
import (
"fmt"
)
type person struct {
name string
age byte
isDead bool
}
func whoIsDead(personMap map[string]person) {
for name, _ := range personMap {
if personMap[name].age < 50 {
personMap[name].isDead = true
}
}
}
func main() {
p1 := person{name: "zzy", age: 100}
p2 := person{name: "dj", age: 99}
p3 := person{name: "px", age: 20}
personMap := map[string]person{
p1.name: p1,
p2.name: p2,
p3.name: p3,
}
whoIsDead(personMap)
for _, v :=range personMap {
if v.isDead {
fmt.Printf("%s is dead\n", v.name)
}
}
}
Compile error:
[cannot assign to struct field personMap[name].isDead in map
]The reason is that the map element is not addressable, which means you can get personMap[name], but you cannot modify it. The solution is 2, 1 is value of map using the pointer type of strct, and 2 is a temporary variable, set back after each fetch.
(1) Change the element in map to the pointer to struct.
package main
import (
"fmt"
)
type person struct {
name string
age byte
isDead bool
}
func whoIsDead(people map[string]*person) {
for name, _ := range people {
if people[name].age < 50 {
people[name].isDead = true
}
}
}
func main() {
p1 := &person{name: "zzy", age: 100}
p2 := &person{name: "dj", age: 99}
p3 := &person{name: "px", age: 20}
personMap := map[string]*person {
p1.name: p1,
p2.name: p2,
p3.name: p3,
}
whoIsDead(personMap)
for _, v :=range personMap {
if v.isDead {
fmt.Printf("%s is dead\n", v.name)
}
}
}
Output results:
[px is dead
](2) Overwrite the original element with temporary variables.
package main
import (
"fmt"
)
type person struct {
name string
age byte
isDead bool
}
func whoIsDead(people map[string]person) {
for name, _ := range people {
if people[name].age < 50 {
tmp := people[name]
tmp.isDead = true
people[name] = tmp
}
}
}
func main() {
p1 := person{name: "zzy", age: 100}
p2 := person{name: "dj", age: 99}
p3 := person{name: "px", age: 20}
personMap := map[string]person {
p1.name: p1,
p2.name: p2,
p3.name: p3,
}
whoIsDead(personMap)
for _, v :=range personMap {
if v.isDead {
fmt.Printf("%s is dead\n", v.name)
}
}
}
Output results:
[px is dead
]
2.2 map concurrent read-write problem
Shared map needs to be locked when reading and writing concurrently. First look at the error example:
package main
import (
"fmt"
"time"
)
var m = make(map[int]int)
func main() {
//1 a go Process writing map
go func(){
for i := 0; i < 10000; i++ {
m[i] = i
}
}()
//1 a go Cheng read map
go func(){
for i := 0; i < 10000; i++ {
fmt.Println(m[i])
}
}()
time.Sleep(time.Second*20)
}
Operation error:
[fatal error: concurrent map read and map write
]Mutual exclusive access can be achieved using a read-write lock (sync.RWMutex).
package main
import (
"fmt"
"time"
"sync"
)
var m = make(map[int]int)
var rwMutex sync.RWMutex
func main() {
//1 a go Process writing map
go func(){
rwMutex.Lock()
for i := 0; i < 10000; i++ {
m[i] = i
}
rwMutex.Unlock()
}()
//1 a go Cheng read map
go func(){
rwMutex.RLock()
for i := 0; i < 10000; i++ {
fmt.Println(m[i])
}
rwMutex.RUnlock()
}()
time.Sleep(time.Second*20)
}
Normal operation output:
[
0
1
...
9999
These are the details of Golang using map. For more information about golang map, please pay attention to other articles on this site.