Skip to content

Commit 3e5f46d

Browse files
committed
Rework maps section
Closes #267
1 parent a15642a commit 3e5f46d

File tree

8 files changed

+177
-62
lines changed

8 files changed

+177
-62
lines changed

topics/go/language/maps/README.md

+12-5
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ Maps provide a data structure that allow for the storage and management of key/v
55
## Notes
66

77
* Maps provide a way to store and retrieve key/value pairs.
8-
* The map key must be a value that can be used in an assignment statement.
8+
* Reading an absent key returns the zero value for the map's value type.
99
* Iterating over a map is always random.
10+
* The map key must be a value that is comparable.
11+
* Elements in a map are not addressable.
12+
* Maps are a reference type.
1013

1114
## Links
1215

@@ -17,10 +20,14 @@ http://www.goinggo.net/2013/12/macro-view-of-map-internals-in-go.html
1720

1821
## Code Review
1922

20-
[Declare, initialize and iterate](example1/example1.go) ([Go Playground](https://play.golang.org/p/xMpg8hv_1pD))
21-
[Map literals and delete](example2/example2.go) ([Go Playground](https://play.golang.org/p/exyL4z8STLt))
22-
[Map key restrictions](example3/example3.go) ([Go Playground](https://play.golang.org/p/j7Rrqn4XiBR))
23-
[Sorting maps by key](example4/example4.go) ([Go Playground](https://play.golang.org/p/fkr0722d-eg))
23+
TODO renumber
24+
[Declare, write, read, and delete](example1/example1.go) ([Go Playground](https://play.golang.org/p/3w6zgywPD3w))
25+
[Absent keys](example2/example2.go) ([Go Playground](https://play.golang.org/p/5KHMfmL2SyA))
26+
[Map key restrictions](example3/example3.go) ([Go Playground](https://play.golang.org/p/lfl967ocaKv))
27+
[Map literals and range](example4/example4.go) ([Go Playground](https://play.golang.org/p/0KFlxby2a0z))
28+
[Sorting maps by key](example5/example5.go) ([Go Playground](https://play.golang.org/p/XADXCQqn2pJ))
29+
[Taking an element's address](example6/example6.go) ([Go Playground](https://play.golang.org/p/4phv1S1wZWh))
30+
[Maps are Reference Types](example7/example7.go) ([Go Playground](https://play.golang.org/p/7jEDn1yhg5v))
2431

2532
## Exercises
2633

+22-13
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// All material is licensed under the Apache License Version 2.0, January 2004
22
// http://www.apache.org/licenses/LICENSE-2.0
33

4-
// Sample program to show how to declare, initialize and iterate
5-
// over a map. Shows how iterating over a map is random.
4+
// Sample program to show how to initialize a map, write to
5+
// it, then read and delete from it.
66
package main
77

88
import "fmt"
99

10-
// user defines a user in the program.
10+
// user represents someone using the program.
1111
type user struct {
1212
name string
1313
surname string
@@ -25,16 +25,25 @@ func main() {
2525
users["Mouse"] = user{"Mickey", "Mouse"}
2626
users["Jackson"] = user{"Michael", "Jackson"}
2727

28-
// Iterate over the map.
29-
for key, value := range users {
30-
fmt.Println(key, value)
31-
}
28+
// Read the value at a specific key.
29+
mouse := users["Mouse"]
3230

33-
fmt.Println()
31+
fmt.Printf("%+v\n", mouse)
3432

35-
// Iterate over the map and notice the
36-
// results are different.
37-
for key := range users {
38-
fmt.Println(key)
39-
}
33+
// Replace the value at the Mouse key.
34+
users["Mouse"] = user{"Jerry", "Mouse"}
35+
36+
// Read the Mouse key again.
37+
fmt.Printf("%+v\n", users["Mouse"])
38+
39+
// Delete the value at a specific key.
40+
delete(users, "Roy")
41+
42+
// Check the length of the map. There are only 3 elements.
43+
fmt.Println(len(users))
44+
45+
// It is safe to delete an absent key.
46+
delete(users, "Roy")
47+
48+
fmt.Println("Goodbye.")
4049
}
+26-26
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
11
// All material is licensed under the Apache License Version 2.0, January 2004
22
// http://www.apache.org/licenses/LICENSE-2.0
33

4-
// Sample program to show how to declare and initialize a map
5-
// using a map literal and delete a key.
4+
// Sample program to show how maps behave when you read an
5+
// absent key.
66
package main
77

88
import "fmt"
99

10-
// user defines a user in the program.
11-
type user struct {
12-
name string
13-
surname string
14-
}
15-
1610
func main() {
1711

18-
// Declare and initialize the map with values.
19-
users := map[string]user{
20-
"Roy": {"Rob", "Roy"},
21-
"Ford": {"Henry", "Ford"},
22-
"Mouse": {"Mickey", "Mouse"},
23-
"Jackson": {"Michael", "Jackson"},
24-
}
12+
// Create a map to track scores for players in a game.
13+
scores := make(map[string]int)
2514

26-
// Iterate over the map.
27-
for key, value := range users {
28-
fmt.Println(key, value)
29-
}
15+
// Read the element at key "anna". It is absent so we get
16+
// the zero-value for this map's value type.
17+
score := scores["anna"]
3018

31-
// Delete the Roy key.
32-
delete(users, "Roy")
19+
fmt.Println("Score:", score)
3320

34-
fmt.Println("=================")
21+
// If we need to check for the presence of a key we use
22+
// a 2 variable assignment. The 2nd variable is a bool.
23+
score, ok := scores["anna"]
3524

36-
// Find the Roy key.
37-
u, found := users["Roy"]
25+
fmt.Println("Score:", score, "Present:", ok)
26+
27+
// We can leverage the zero-value behavior to write
28+
// convenient code like this:
29+
scores["anna"]++
30+
31+
// Without this behavior we would have to code in a
32+
// defensive way like this:
33+
if n, ok := scores["anna"]; ok {
34+
scores["anna"] = n + 1
35+
} else {
36+
scores["anna"] = 1
37+
}
3838

39-
// Display the value and found flag.
40-
fmt.Println("Roy", found, u)
39+
score, ok = scores["anna"]
40+
fmt.Println("Score:", score, "Present:", ok)
4141
}

topics/go/language/maps/example3/example3.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ package main
77

88
import "fmt"
99

10-
// user defines a user in the program.
10+
// user represents someone using the program.
1111
type user struct {
1212
name string
1313
surname string
1414
}
1515

16-
// users define a set of users.
16+
// users defines a set of users.
1717
type users []user
1818

1919
func main() {
2020

21-
// Declare and make a map uses a slice of users as the key.
21+
// Declare and make a map that uses a slice as the key.
2222
u := make(map[users]int)
2323

2424
// ./example3.go:22: invalid map key type users
+12-15
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
// All material is licensed under the Apache License Version 2.0, January 2004
22
// http://www.apache.org/licenses/LICENSE-2.0
33

4-
// Sample program to show how to walk through a map by alphabetical key order.
4+
// Sample program to show how to declare, initialize and iterate
5+
// over a map. Shows how iterating over a map is random.
56
package main
67

7-
import (
8-
"fmt"
9-
"sort"
10-
)
8+
import "fmt"
119

12-
// user defines a user in the program.
10+
// user represents someone using the program.
1311
type user struct {
1412
name string
1513
surname string
@@ -25,17 +23,16 @@ func main() {
2523
"Jackson": {"Michael", "Jackson"},
2624
}
2725

28-
// Pull the keys from the map.
29-
var keys []string
30-
for key := range users {
31-
keys = append(keys, key)
26+
// Iterate over the map printing each key and value.
27+
for key, value := range users {
28+
fmt.Println(key, value)
3229
}
3330

34-
// Sort the keys alphabetically.
35-
sort.Strings(keys)
31+
fmt.Println()
3632

37-
// Walk through the keys and pull each value from the map.
38-
for _, key := range keys {
39-
fmt.Println(key, users[key])
33+
// Iterate over the map printing just the keys.
34+
// Notice the results are different.
35+
for key := range users {
36+
fmt.Println(key)
4037
}
4138
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// All material is licensed under the Apache License Version 2.0, January 2004
2+
// http://www.apache.org/licenses/LICENSE-2.0
3+
4+
// Sample program to show how to walk through a map by
5+
// alphabetical key order.
6+
package main
7+
8+
import (
9+
"fmt"
10+
"sort"
11+
)
12+
13+
// user represents someone using the program.
14+
type user struct {
15+
name string
16+
surname string
17+
}
18+
19+
func main() {
20+
21+
// Declare and initialize the map with values.
22+
users := map[string]user{
23+
"Roy": {"Rob", "Roy"},
24+
"Ford": {"Henry", "Ford"},
25+
"Mouse": {"Mickey", "Mouse"},
26+
"Jackson": {"Michael", "Jackson"},
27+
}
28+
29+
// Pull the keys from the map.
30+
var keys []string
31+
for key := range users {
32+
keys = append(keys, key)
33+
}
34+
35+
// Sort the keys alphabetically.
36+
sort.Strings(keys)
37+
38+
// Walk through the keys and pull each value from the map.
39+
for _, key := range keys {
40+
fmt.Println(key, users[key])
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// All material is licensed under the Apache License Version 2.0, January 2004
2+
// http://www.apache.org/licenses/LICENSE-2.0
3+
4+
// Sample program to show that you cannot take the address
5+
// of an element in a map.
6+
package main
7+
8+
// player represents someone playing our game.
9+
type player struct {
10+
name string
11+
score int
12+
}
13+
14+
func main() {
15+
16+
// Declare a map with initial values using a map literal.
17+
players := map[string]player{
18+
"anna": {"Anna", 42},
19+
"jacob": {"Jacob", 21},
20+
}
21+
22+
// Trying to take the address of a map element fails.
23+
anna := &players["anna"]
24+
anna.score++
25+
26+
// ./example4.go:23:10: cannot take the address of players["anna"]
27+
28+
// Instead take the element, modify it, and put it back.
29+
player := players["anna"]
30+
player.score++
31+
players["anna"] = player
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// All material is licensed under the Apache License Version 2.0, January 2004
2+
// http://www.apache.org/licenses/LICENSE-2.0
3+
4+
// Sample program to show how maps are reference types.
5+
package main
6+
7+
import "fmt"
8+
9+
func main() {
10+
11+
// Initialize a map with values.
12+
scores := map[string]int{
13+
"anna": 21,
14+
"jacob": 12,
15+
}
16+
17+
// Pass the map to a function to perform some mutation.
18+
double(scores, "anna")
19+
20+
// See the change is visible in our map.
21+
fmt.Println("Score:", scores["anna"])
22+
}
23+
24+
// double finds the score for a specific player and
25+
// multiplies it by 2.
26+
func double(scores map[string]int, player string) {
27+
scores[player] = scores[player] * 2
28+
}

0 commit comments

Comments
 (0)