Intro
In this post, I'll discuss the behavior of maps in Go when passed as arguments into functions.
I'll also discuss how to avoid modifying the original map when passing it to a function.
Maps in Go
Maps in Go are a collection of key-value pairs.
They are used to store and retrieve values based on a unique key.
1score := map[string]int{
2 "Tony": 30,
3 "Steve": 10,
4 "Thor": 2,
5}
1score := map[string]int{
2 "Tony": 30,
3 "Steve": 10,
4 "Thor": 2,
5}
Here we have a map called score
that stores the scores of three players.
Where the key is the player's name and the value is the player's score.
Passing maps as arguments to a function
In Go, when we pass an argument to a function, it can be passed either by value or by reference.
Let's illustrate this through an example:
1func main() {
2 var score int = 10
3 fmt.Println(score) // 10
4 incrementScore(score)
5 fmt.Println(score) // 10
6}
7
8func incrementScore(score int) {
9 score++
10}
1func main() {
2 var score int = 10
3 fmt.Println(score) // 10
4 incrementScore(score)
5 fmt.Println(score) // 10
6}
7
8func incrementScore(score int) {
9 score++
10}
In this example, we pass the score
into the incrementScore()
function, but the printed value remains 10.
This is because arguments are passed by value in Go.
To modify the original value, we can pass the score as a reference by changing the function to accept a pointer to an int
variable:
1func main() {
2 var score int = 10
3 fmt.Println(score) // 10
4 incrementScore(&score)
5 fmt.Println(score) // 11
6}
7
8func incrementScore(score *int) {
9 *score++
10}
1func main() {
2 var score int = 10
3 fmt.Println(score) // 10
4 incrementScore(&score)
5 fmt.Println(score) // 11
6}
7
8func incrementScore(score *int) {
9 *score++
10}
Now, the score
variable has been successfully mutated, and its value is 11.
We use a pointer to modify the value of a variable from the incrementScore()
function.
Now, let's shift our focus to maps in Go.
Maps are reference types, meaning that when we pass a map to a function, we pass a reference to the underlying data structure, not a copy of the map.
Although maps themselves are not mutable, the data they reference is mutable:
1func main() {
2 score := map[string]int{
3 "Tony": 30,
4 "Steve": 10,
5 "Thor": 2,
6 }
7 fmt.Println(score) // map[Steve:10 Thor:2 Tony:30]
8 changeScores(score)
9 fmt.Println(score) // map[Steve:10 Thor:2 Tony:1000]
10}
11
12func changeScores(scores map[string]int) {
13 scores["Tony"] = 1000
14}
1func main() {
2 score := map[string]int{
3 "Tony": 30,
4 "Steve": 10,
5 "Thor": 2,
6 }
7 fmt.Println(score) // map[Steve:10 Thor:2 Tony:30]
8 changeScores(score)
9 fmt.Println(score) // map[Steve:10 Thor:2 Tony:1000]
10}
11
12func changeScores(scores map[string]int) {
13 scores["Tony"] = 1000
14}
In this example, modifications made to the map inside the changeScores()
function are reflected in the original map outside the function.
To avoid modifying the original map, we can create a copy of the map inside the function:
1func main() {
2 score := map[string]int{
3 "Tony": 30,
4 "Steve": 10,
5 "Thor": 2,
6 }
7 fmt.Println(score)
8 changedScore := changeScores(score)
9 fmt.Println(changedScore)
10}
11
12func changeScores(scores map[string]int) map[string]int {
13 newScores := make(map[string]int)
14 for key, value := range scores {
15 newScores[key] = value
16 }
17 newScores["Tony"] = 1000
18 return newScores
19}
1func main() {
2 score := map[string]int{
3 "Tony": 30,
4 "Steve": 10,
5 "Thor": 2,
6 }
7 fmt.Println(score)
8 changedScore := changeScores(score)
9 fmt.Println(changedScore)
10}
11
12func changeScores(scores map[string]int) map[string]int {
13 newScores := make(map[string]int)
14 for key, value := range scores {
15 newScores[key] = value
16 }
17 newScores["Tony"] = 1000
18 return newScores
19}
To summarize:
- Maps in Go are reference types.
- Passing a map to a function passes a reference to the underlying data structure.
- Modifications to the map inside a function affect the original map outside the function.
- The map itself is immutable.
- To avoid modifying the original map, create a copy of the map before making changes inside a function.