Understanding Maps and Structs in Go
As part of my ongoing journey to master Go, I’ve dived deep into two fundamental concepts maps and structs. Today, I had the chance to explore how maps help in managing collections of data, and how structs are useful for organizing complex data types. Here’s a breakdown of what I learned and how I applied it.
Maps
Maps are one of the most flexible collection types in Go, allowing you to store key-value pairs. This makes them incredibly useful for when you need to look up values by a key.
Declaring Maps
In Go, you can declare a map like this.
var nilMap map[string]int
This map is currently nil
, so you can’t store anything in it yet. You need to initialize it before usage. Here's an example of initializing a map with string slices
teams := map[string][]string{
"Orcas": {"Fred", "Ralph", "Bijou"},
"Lions": {"Sarah", "Peter", "Billie"},
"Kittens": {"Waldo", "Raul", "Ze"},
}
fmt.Println(teams["Lions"]) // Outputs: [Sarah Peter Billie]
Using Maps
You can easily add values to a map or retrieve them by key. Here’s an example.
totalWins := map[string]int{}
totalWins["Orcas"] = 1
totalWins["Lions"] = 2
fmt.Println(totalWins["Orcas"]) // Outputs: 1
fmt.Println(totalWins["Kittens"]) // Outputs: 0 (since it's not defined yet)
totalWins["Kittens"]++ // Increments the value
fmt.Println(totalWins["Kittens"]) // Outputs: 1
The Comma-Ok Idiom
When checking whether a key exists in a map, Go offers a simple way to do so with the comma-ok idiom
m := map[string]int{
"hello": 5,
"world": 0,
}
v, ok := m["hello"]
fmt.Println(v, ok) // Outputs: 5 true
v, ok = m["goodbye"]
fmt.Println(v, ok) // Outputs: 0 false
This is especially helpful in avoiding potential nil pointer errors when working with map lookups.
Deleting Keys
You can delete entries from a map using the delete()
function
delete(m, "hello")
fmt.Println(m) // Outputs: map[world:10]
Using Maps as Sets
Go doesn’t have a built-in set type, but you can use a map as a set by ignoring the values and focusing on the keys
inSet := map[int]bool{}
vals := []int{5, 10, 2, 5, 7, 3, 9, 1, 2, 10}
for _, v := range vals {
inSet[v] = true
}
fmt.Println(len(vals), len(inSet)) // Outputs: 10 8 (because duplicates are ignored)
This approach is common when you need to track whether an element exists in a collection.
Structs: Organizing Complex Data
Structs in Go are used to define complex data types. They are analogous to classes in other languages, but without methods. Structs are especially useful for grouping related data.
Declaring and Initializing Structs
Here’s how you declare and initialize a basic struct
type person struct {
name string
age int
pet string
}
bob := person{
name: "Bob",
age: 40,
pet: "dog",
}
fmt.Println(bob)
You can also initialize structs using different approaches:
Struct Literal Style without Field Names
julia := person{"Julia", 20, "cat"}
Struct Literal Style with Field Names
beth := person{ name: "Beth", age: 30, }
Using Dot Notation
var fred person fred.name = "Fred" fred.age = 22 fred.pet = "parrot"
Anonymous Structs
You can also declare and use structs without naming them
pet := struct {
name string
kind string
}{
name: "Fido",
kind: "dog",
}
fmt.Println(pet)
Comparing and Converting Structs
Structs can be compared if their fields are identical, but you can’t compare different struct types
type firstPerson struct {
name string
age int
}
type secondPerson struct {
name string
age int
}
var a firstPerson
var b secondPerson
// You can't compare 'a' and 'b' because they're different types
However, you can convert one struct type to another if they have the same fields
Next Up
I’ll be diving into blocks, shadowing, and control structures in Go. These topics will enhance my understanding of how Go handles variable scope, code organization, and decision-making processes in a program
Subscribe to my newsletter
Read articles from Sahal Imran directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by