How to pretty print the contents of a sync Map

Issue

I want to pretty print the contents of a sync map in Go.
I have a sync.Map data I want to print the contents of it.

To view the value of a specific key SiteData I can run the following code.

var data sync.Map
siteData := map[string]string{"Name": "StackOverflow"}
data.Store("SiteData", siteData)
temp, _ := data.Load("SiteData") 
b, _ := json.MarshalIndent(temp, "", " ")
fmt.Println(string(b))

But I wish to print the entire map at once. This is because the data can have many keys and I want to print them at once.

Running the below code doesn’t work and prints {}

var data sync.Map
siteData := map[string]string{"Name": "StackOverflow"}
data.Store("SiteData", siteData)
b, _ := json.MarshalIndent(data, "", " ")
fmt.Println(string(b))

Solution

Fields (internals) of sync.Map are not exported, so they can’t be accessed, and more importantly they can’t be accessed without synchronization. So you can’t just print the contents of a sync.Map.

What you may do is iterate over all entries of your sync.Map, build an “ordinary” map from it, and display that. Note that the “ordinary” map must have string key type (maps with interface{} key type are not supported by the encoding/json package). We may simply convert interface{} keys to string using fmt.Sprint(). To get all entries, you may use Map.Range().

For example:

var data sync.Map
data.Store("SiteData", map[string]string{
    "Name": "StackOverflow",
    "Url":  "https://so.com",
})
data.Store("Else", "something else")

m := map[string]interface{}{}
data.Range(func(key, value interface{}) bool {
    m[fmt.Sprint(key)] = value
    return true
})

b, err := json.MarshalIndent(m, "", " ")
if err != nil {
    panic(err)
}
fmt.Println(string(b))

This will output (try it on the Go Playground):

{
 "Else": "something else",
 "SiteData": {
  "Name": "StackOverflow",
  "Url": "https://so.com"
 }
}

Answered By – icza

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.