Often in Go programs we have related data—for example, we might have X and Y coordinates. With a struct
, we can store these together.
With structs, we create new types that contain different fields and methods. Ints and strings can be stored in structs. We use the struct
keyword.
struct
We specify the type Location struct
: this has 3 fields and no methods. The "x" and "y" fields are both ints, and there is a bool
that indicates validity.
struct
. The Location here is not an instance—it is something we must create with new.new()
syntax for creating an instance of struct
type. We assign the "x" field of the struct
to a value.struct
. We can just specify the field names we want to set.package main import "fmt" type Location struct { x int y int valid bool } func main() { // Version 1: create a Location struct instance and set a field. loc := new(Location) loc.x = 10 fmt.Println(loc.x) // Version 2: use initializer syntax. loc2 := Location{x: 10} fmt.Println(loc2.x) }10 10
struct
pointersThis program reuses our Location struct
. It specifies two fields of the struct
on one line. And in main()
, it creates a slice of struct
pointers.
fmt.Println
to display the struct
data to the console.package main import "fmt" type Location struct { x, y int valid bool } func main() { // Create empty slice of struct pointers. places := []*Location{} // Create struct and append it to the slice. loc := new(Location) loc.x = 10 loc.y = 20 loc.valid = true places = append(places, loc) // Create another struct. loc = new(Location) loc.x = 5 loc.y = 8 loc.valid = true places = append(places, loc) // Loop over all indexes in the slice. // ... Print all struct data. for i := range(places) { place := places[i] fmt.Println("Location:", place) } }Location: &{10 20 true} Location: &{5 8 true}
A struct
can be used as the key of a map. We create struct
instances and use their values to assign map data. We access the value of a struct
"m" with "*m" to add the key.
package main import "fmt" type Measure struct { size int unit string } func main() { // A map with struct keys. storage := map[Measure]bool{} // Add 3 structs as keys in the map. m := new(Measure) m.size = 10 m.unit = "centimeters" storage[*m] = true m = new(Measure) m.size = 20 m.unit = "feet" storage[*m] = true m = new(Measure) m.size = 10 m.unit = "decibels" storage[*m] = true // There are 3 keys in the map. fmt.Println("Map len", len(storage)) // Create structs to look up values in the map. key := new(Measure) key.size = 10 key.unit = "centimeters" v := storage[*key] fmt.Println("Result", key, v) key = new(Measure) key.size = 100 key.unit = "decibels" v = storage[*key] fmt.Println("Result", key, v) }Map len 3 Result &{10 centimeters} true Result &{100 decibels} false
With interfaces, we create abstractions that can be used to reference many types at once. This is confusing at first, but leads to clearer programs.
With structs, we combine fields and funcs. We can use slices and maps with structs to build more complex collections—this is powerful and intuitive.