Video Coming Soon...
16: The Type System: Structs
WARNING This exercise is in DRAFT status, so there may be errors. If you find any, please email me at help@learncodethehardway.com so I can fix them.
From now on everything you'll learn about Go is some combination of--or is very similar to--something you already know. For example, Structs (the topic of this exercise) are nothing more than a collection of variables under one name. You alread know what a variable is, and how variables have a type (int
, float32
, etc.), so struct
is nothing more than a grouping of those.
Another way to describe a struct
is, "A new type that is a collection of other types." You can also think of a struct
as a single row from a database or spreadsheet. Each column of the row has a name and a type (INTEGER
, FLOAT
, TEXT
) and acts as a cohesive collection of those columns.
Using struct
Let's look at a small example:
type Position struct {
X int
Y int
}
Here we have a Position
struct, and as you can see we create it with the type
keyword. That identifies it as a new type similar to int
or float32
, but Position
is composed of two fields (aka variables) X
and Y
.
This Position
type can then be used as the type of a variable like so:
// declaring a variable as Position
var player_at Position
// or, with the := like so
enemy_at := Position{10,10}
To access the fields (contents) of the struct
you use the .
(dot) similar to how you use it with fmt.Println
. The .
(dot) usually means "get from" or "access" in many languages. For example, to get the position of an enemy I would do:
x_field := enemy_at.X
y_field := enemy_at.Y
Printing the coordinate would look something like this:
fmt.Println("x=", enemy_at.x, "y=", enemy_at.y)
Finally, you can set any field to a new value by simply treating it like a variable and use =
(but not :=
):
enemy_at.X = 100
enemy_at.Y = 20
The Code
Here's the code for this exercise, where we make some Animal
structs and do things with the fields:
View Source file ex16/main.go Only
package main
import (
"fmt"
)
type Animal struct {
Name string
Age int
Species string
Weight float64
}
func PrintAnimal(who Animal) {
// you can pass your structs directly to Println
fmt.Println("Your Pet:", who)
}
func main() {
frankie := Animal{"Fankie", 5, "Dog", 20.5};
// access a field in a struct with .
fmt.Println("Name:", frankie.Name);
PrintAnimal(frankie)
// change a field by assigning to it
frankie.Weight = 25.6
fmt.Println("Your Pet Gained Weight:", frankie)
// make a copy of a struct
miss_snuffles := frankie
// test if they're equal
if(miss_snuffles == frankie) {
// change it with the . and =
miss_snuffles.Name = "Miss Snuffles"
miss_snuffles.Species = "Cat"
miss_snuffles.Weight = 4.0
}
// pass structs to functions
PrintAnimal(frankie)
PrintAnimal(miss_snuffles)
}
The Breakdown
As usual I'm only going to describe lines that are new to you.
type Animal struct {
-- Create theAnimal
struct.Name string
--Name
field of typestring
Age int
--Age
field of typeint
Species string
--Species
field of typestring
Weight float64
--Weight
field of typefloat64
}
-- Ends the structfunc PrintAnimal(who Animal) {
-- Passing an animal to a function.frankie := Animal{"Fankie", 5, "Dog", 20.5};
-- Create an animal that starts off withName="Frankie"
and so on.fmt.Println("Name:", frankie.Name);
-- Print theName
.PrintAnimal(frankie)
-- CallPrintAnimal
withfrankie
frankie.Weight = 25.6
-- Changefrankie
'sWeight
to25.6
fmt.Println("Your Pet Gained Weight:", frankie)
-- Shamefrankie
for gaining weight.miss_snuffles := frankie
-- Make a copy offrankie
.if(miss_snuffles == frankie) {
-- Test that two structs are equal.miss_snuffles.Name = "Miss Snuffles"
-- Change this newAnimal
to have different settings.miss_snuffles.Species = "Cat"
-- It's a cat.miss_snuffles.Weight = 4.0
-- Cats are small.PrintAnimal(frankie)
-- Printfrankie
again.PrintAnimal(miss_snuffles)
-- Printmiss_snuffles
, so you can see how it changed.
Make sure you understand each line, and if there any you don't then try to figure out why. Sometimes experimenting with lines of code you don't get will help you understand it.
The Practice
- Break It -- Try assigning to fields with the wrong names, give them the wrong types (like try to set an
int
to astring
). - Change It -- Can you add to
Animal
? Can you create anotherstruct
? - Remake It -- As usual, write a description the recreate it from memory using the description. The more you do this, the better you'll get.
Study Drills
From now on I'm going to point you at the Go Specification and ask you to read it and try to understand it. You may not understand everything there, but it's good to know where it is.
- Read the Go Specification for
struct
. - Add a struct that is inside the
Animal
struct as a new field. - Try using
fmt.Println
directly on thefrankie
variable. - Using what you know about reading input from the last module, can you store a user's input into a
struct
?
Register for Learn Go the Hard Way
Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.