Are maps passed by value or by reference in Go?

Go

Go Problem Overview


Are maps passed by value or reference in Go ?

It is always possible to define a function as following, but is this an overkill ?

func foo(dat *map[string]interface{}) {...}

Same question for return value. Should I return a pointer to the map, or return the map as value ?

The intention is of course to avoid unnecessary data copy.

Go Solutions


Solution 1 - Go

In this thread you will find your answer :

https://stackoverflow.com/questions/28384343/golang-accessing-a-map-using-its-reference

> You don't need to use a pointer with a map. > > Map types are reference types, like pointers or slices[1] > > If you needed to change the Session you could use a pointer: > > map[string]*Session > > https://blog.golang.org/go-maps-in-action

Solution 2 - Go

Here are some parts from If a map isn’t a reference variable, what is it? by Dave Cheney:

> A map value is a pointer to a runtime.hmap structure.

and conclusion:

> Conclusion > > Maps, like channels, but unlike slices, are just pointers to runtime > types. As you saw above, a map is just a pointer to a runtime.hmap > structure. > > Maps have the same pointer semantics as any other pointer value in a > Go program. There is no magic save the rewriting of map syntax by the > compiler into calls to functions in runtime/hmap.go.

And an interesting bit about history/explanation of map syntax:

> If maps are pointers, shouldn’t they be *map[key]value? > > It’s a good question that if maps are pointer values, why does the > expression make(map[int]int) return a value with the type > map[int]int. Shouldn’t it return a *map[int]int? Ian Taylor > answered this recently in a golang-nuts thread1. > > > In the very early days what we call maps now were written as pointers, > > so you wrote *map[int]int. We moved away from that when we realized > > that no one ever wrote map without writing *map. > > > Arguably renaming the type from *map[int]int to map[int]int, while > confusing because the type does not look like a pointer, was less > confusing than a pointer shaped value which cannot be dereferenced.

Solution 3 - Go

No. Maps are reference by default.

	package main

	import "fmt"

	func mapToAnotherFunction(m map[string]int) {
		m["hello"] = 3
		m["world"] = 4
		m["new_word"] = 5
	}

	// func mapToAnotherFunctionAsRef(m *map[string]int) {
	// m["hello"] = 30
	// m["world"] = 40
	// m["2ndFunction"] = 5
	// }

	func main() {
		m := make(map[string]int)
		m["hello"] = 1
		m["world"] = 2

		// Initial State
		for key, val := range m {
			fmt.Println(key, "=>", val)
		}

		fmt.Println("-----------------------")

		mapToAnotherFunction(m)
		// After Passing to the function as a pointer
		for key, val := range m {
			fmt.Println(key, "=>", val)
		}

		// Try Un Commenting This Line
		fmt.Println("-----------------------")

		// mapToAnotherFunctionAsRef(&m)
		// // After Passing to the function as a pointer
		// for key, val := range m {
		//	fmt.Println(key, "=>", val)
		// }

		// Outputs
		// hello => 1
		// world => 2
		// -----------------------
		// hello => 3
		// world => 4
		// new_word => 5
		// -----------------------

	}

From Golang Blog-

>Map types are reference types, like pointers or slices, and so the value of m above is nil; it doesn't point to an initialized map. A nil map behaves like an empty map when reading, but attempts to write to a nil map will cause a runtime panic; don't do that. To initialize a map, use the built in make function:

// Ex of make function
m = make(map[string]int)

Code Snippet Link Play with it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionchmikeView Question on Stackoverflow
Solution 1 - GoBoris Le MéecView Answer on Stackoverflow
Solution 2 - GoAkavallView Answer on Stackoverflow
Solution 3 - GoalaminView Answer on Stackoverflow