"Golang Notes" key randomization problem and solution for traversing map

Source: Internet
Author: User

A previous note has analyzed that the go map is implemented using HashMap at the bottom. Since the efficient hash function is definitely not a sequential hash of the key, it is similar to the HashMap implemented in other languages, where the key-value insertion sequence and the traversal of the map key when using the Go language map The order of access is not the same. The students who are familiar with HashMap should be very clear about this situation.
Therefore, this article is certainly not this, but a more surprising situation, the following begins to explain.

1. When you traverse a map by range, the order of key is randomized
!
This phenomenon is very rare in other languages, such as the C language implementation of HashMap, usually with an array (that is, a contiguous memory space) to save the key, although the key distribution sequence and interpolation The order is inconsistent, but after the k-v data has been populated, the order of the entire HashMap key is fixed, so the order of the key to be accessed each round of the subsequent traversal of this hashmap is is consistent.
But when the go language traverses the map through range, it does randomize the key sequence of the map. The following is a simple verification procedure.

Map_range_rand.gopackage Mainimport (    "FMT") func main () {    m: = Make (map[string]string)    m["Hello"] = " echo Hello "    m["] = "echo World"    m["Go" = "echo Go"    m["was"] = "echo is"    m["cool"] = "echo Cool"    For k, V: = range m {        fmt. Printf ("K=%v, v=%v\n", K, V)    }}
In the Go v1.4 environment, execute go build map_range_rand.go after compiling, run the output of 2 binaries, the result is as follows.

run the output for the 1th time:
$./map_range_rand K=is, V=echo isk=cool, V=echo Coolk=hello, V=echo Hellok=world, V=echo worldk=go, V=echo go
Run the output for the 2nd time:
$./map_range_rand K=go, V=echo gok=is, V=echo isk=cool, V=echo Coolk=hello, V=echo Hellok=world, V=echo World
Run the output for the 3rd time:
$./map_range_rand K=hello, V=echo Hellok=world, V=echo Worldk=go, V=echo gok=is, V=echo isk=cool, V=echo cool
It is clear to see that the order of key is different each time it is traversed.
Later in the Golang official blog article go maps in action, confirmed that this phenomenon exists, and is the go language designers intentionally, in this article on the iteration order of the note mentioned:
When iterating-a map with a range loop, the iteration order is not specified and is not guaranteed to be the same From one iteration to the next. Since Go 1 The runtime randomizes map Iteration order, as programmers relied on the stable iteration order of the previous implementation.
It seems that when you use the go map, you may rely on the stable traversal order of the map key in your business logic, which is not guaranteed by the go underlying implementation. Therefore, the go language simply randomization the key sequence to remind you not to rely on the range to traverse the returned key sequence.
Oddly, I ran the above sample code in the Golang 1.2 environment, and the order of key in the output was non-randomized.
However, this default order must not be relied upon in any way.

2. How to solve the randomization problem when the business depends on the key order

in fact, the go maps in action article has given a workaround:
If you require a stable iteration order you must maintain a separate data structure this specifies that order.
Visible, you need to maintain a data structure to maintain an orderly key, and then traverse the map according to the ordered key.
The following is a solution to the stable traversal order given in the previous example.
Package Mainimport ("FMT", "    sort") Func main () {    m: = Make (map[string]string)    m["Hello"] = "echo Hello"    m ["World"] = "echo World"    m["Go" = "echo Go"    m["was"] = "echo is"    m["cool"] = "echo Cool"    sorted_keys: = ma Ke ([]string, 0)    for k, _: = range m {        Sorted_keys = append (Sorted_keys, k)    }      //Sort ' string ' Key in Inc Reasing Order    Sort. Strings (Sorted_keys)    for _, K: = Range Sorted_keys {        fmt. Printf ("K=%v, v=%v\n", K, M[k])    }}
In the example above, by introducing sort to the key and then traversing the map according to the ordered keys, the key sequence is fixed each time the map is traversed.
You can verify that the order of key in each execution result is in ascending order by dictionary order:
$./map_range_randk=cool, V=echo Coolk=go, V=echo Gok=hello, V=echo hellok=is, V=echo Isk=world, V=echo World

Resources
Go Blog-go maps in action

=========================== EOF ==========================







"Golang Notes" key randomization problem and solution for traversing map

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.