Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money
XDM, I’m Nezha
In daily development work, we are not unfamiliar with the map data structure. In Golang, of course, there is map
About the use of map, there are a lot of things to pay attention to, if not clear, these matters, the key time may step on the pit, let’s exercise together
1 Remember to initialize using map
Write a demo
- Define a map[int] variable myMap of type int, not initialized
- We can read the value of myMap, which defaults to zero
- However, if we write values into an uninitialized myMap, the program will panic. Remember not to step on the pit here
func main(a){
var myMap map[int]int
fmt.Println("myMap[1] == ",myMap[1])}Copy the code
Program running effect:
# go run main.go
myMap[1] == 0
Copy the code
Add write operations to code:
func main(a){
var myMap map[int]int
fmt.Println("myMap[1] == ",myMap[1])
myMap[1] = 10
fmt.Println("myMap[1] == ",myMap[1])}Copy the code
Program running effect:
# go run main.go
myMap[1] == 0
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/home/admin/golang_study/later_learning/map_test/main.go:20 +0xf3
exit status 2
Copy the code
As expected, the program panic, we need to be very careful in the actual work, the code should be in awe of the heart
2 Map traversal is unordered
- Define a map[int] map of int type and initialize 5 numbers
func main(a) {
myMap := map[int]int{
1: 1.2: 2.3: 3.4: 4.5: 5}
for k := range myMap {
fmt.Println(myMap[k])
}
}
Copy the code
Program running effect:
# go run main.goOne, two, three, four, five# go run main.go5, 1, 2, 3, 4# go run main.go3, 4, 5, 1, 2Copy the code
Run the above code three times and the results will be different three times. Of course, it is possible that the results will be in the same order three times
Because the map in GO is implemented based on a hash table, traversal is out of order
If we need to empty the map, we can just set the corresponding map variable to nil, for example
myMap = nil
Copy the code
3 Maps can also be two-dimensional
Maps can also be two-dimensional, like arrays, or even multi-dimensional, depending on our needs
However, we should note that the definition is just like a two-dimensional array, but the specific use is still different
We can manipulate two-dimensional arrays like this
func main(a) {
myMap := map[int]map[string]string{}
myMap[0] = map[string]string{
"name":"xiaomotong"."hobby":"program",
}
fmt.Println(myMap)
}
Copy the code
Program running effect:
# go run main.go
map[0:map[name:xiaomotong hobby:program]]
Copy the code
We can’t manipulate two-dimensional arrays like this
func main(a) {
myMap := map[int]map[string]string{}
myMap[0] ["name"] = "xiaomotong"
myMap[0] ["hobby"] = "program"
fmt.Println(myMap)
}
Copy the code
Program running effect:
# go run main.go
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/home/admin/golang_study/later_learning/map_test/main.go:17 +0x7f
exit status 2
Copy the code
The reason is simple, and the panic log in the program has already explained the reason
MyMap [0] key is 0, but the value is map[string]string, which needs to be initialized to do write operations
If you want to write it this way, it’s easy, just initialize it
func main(a) {
myMap := map[int]map[string]string{}
myMap[0] = map[string]string{}
myMap[0] ["name"] = "xiaomotong"
myMap[0] ["hobby"] = "program"
fmt.Println(myMap)
}
Copy the code
4 Use this method to obtain the map key
At work, there is a way for us to get all the keys of a map. In this case, how do we get all the keys of a map? XDM who has been exposed to reflection will definitely say, this is very easy.
func main(a) {
myMap := map[int]int{
1: 1.2: 2.3: 3.4: 4.5: 5}
myKey := reflect.ValueOf(myMap).MapKeys()
for v :=range myKey{
fmt.Println(v)
}
}
Copy the code
Run the program go run main.go and the result is as follows:
But as we all know, Reflection in Golang is really neat to write, but it’s really inefficient, so it’s best to use the following method
func main(a) {
myMap := map[int]int{
1: 1.2: 2.3: 3.4: 4.5: 5}
myKey := make([]int.0.len(myMap))
for k :=range myMap{
myKey = append(myKey,myMap[k])
}
fmt.Println(myKey)
}
Copy the code
In this encoding mode, the capacity of myKey slice is set in advance to be the same as the length of map. In this case, when adding keys to myKey in the future, there will be no need for slice expansion
Program running effect:
# go run main.go
[2 3 4 5 1]
Copy the code
And we can see that the key that comes out is not in order either
5 Map is concurrency insecure, sync.map is
Finally, let’s simulate and verify that Golang’s map is not secure
Simulation map is not safe demo, need to open more coroutines to simulate the effect, the experiment, I simulated open 50,000 coroutines
type T struct {
myMap map[int]int
}
func (t *T) getValue(key int) int {
return t.myMap[key]
}
func (t *T) setValue(key int, value int) {
t.myMap[key] = value
}
func main(a) {
ty := T{myMap: map[int]int{}}
wg := sync.WaitGroup{}
wg.Add(50000)
for i := 0; i < 50000; i++ {
go func(i int) {
ty.setValue(i, i)
fmt.Printf("get key == %d, value == %d \n", i, ty.getValue(i))
wg.Done()
}(i)
}
wg.Wait()
fmt.Println("program over !!")}Copy the code
The following information will be displayed when the program changes:
# go run main.go
fatal error: concurrent map writes
...
Copy the code
If you must use a map, you can also add a mutex to solve the problem
We just need to modify the above code, the struct’s defined position, and the function that sets the value
type T struct {
myMap map[int]int
lock sync.RWMutex
}
func (t *T) setValue(key int, value int) {
t.lock.Lock()
defer t.lock.Unlock()
t.myMap[key] = value
}
Copy the code
Go >> map.log to print the output value of the program to a file
After the program runs, it can be seen that the data corresponding to the real printed key is indeed 5000 lines, no problem
Golang provides a concurrency safe map, sync.map. Golang also provides a concurrency safe map, sync.map
Sync.map’s implementation mechanism, in a nutshell, is its own locking, thus controlling concurrency security
Ok, enough for today, language is good language, tools are good tools, we need to use them in order to play their value, without everything is useless
Welcome to like, follow and favorites
Friends, your support and encouragement, I insist on sharing, improve the quality of the power
All right, that’s it for this time
Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.
I am Nezha, welcome to like, see you next time ~