Struct tags
Tags add metadata to fields:
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
Tags are read by packages like encoding/json. They let the JSON field names differ from the Go field names.
Create custom types with structs and attach behavior with methods.
About 2 min of reading
You will build a Person type, attach methods that read or mutate it, and see the difference between value and pointer receivers when a method changes data.
I declare a struct with a string name and an integer age, create a value of it, and print the name. The struct bundles two fields into one named type.
Before you run it, say out loud what it will print. Then open the answer.
I print both fields together to confirm the value carries its data. Each field is accessed with dot notation, so p.Age gives me the integer stored inside.
Before you run it, say out loud what it will print. Then open the answer.
I attach a method to the struct that returns a greeting string built from the name. The receiver (p Person) gives the method access to the value it is called on.
Before you run it, say out loud what it will print. Then open the answer.
I add a pointer-receiver method that increments the age. Pointers let a method mutate the original value, so after calling Birthday the age is now 31.
Before you run it, say out loud what it will print. Then open the answer.
I compare the two receiver styles with a counter. A value-receiver method that increments a field has no effect on the original, which stays at its starting value.
Before you run it, say out loud what it will print. Then open the answer.
Tags add metadata to fields:
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
Tags are read by packages like encoding/json. They let the JSON field names differ from the Go field names.
Choose the receiver type carefully:
func (p Person) Info() string // value copy
func (p *Person) Update() {} // mutates original
If the method mutates the struct, use a pointer receiver. Go lets you call pointer methods on addressable values automatically.
type Person struct {
Name string
Age int
}
p := Person{Name: "Ada", Age: 30}
fmt.Println(p.Name)
A struct bundles related data into one type. Person has a Name and an Age.
Why it works: the type ... struct declaration defines a new named type.
func (p Person) Greet() string {
return "Hello, " + p.Name
}
fmt.Println(p.Greet())
A method has a receiver (p Person). It is like a function that knows which value it belongs to. The receiver works like this in other languages.
Why it works: methods are declared with the receiver syntax before the function name.
func (p *Person) Birthday() {
p.Age++
}
p.Birthday()
fmt.Println(p.Age) // 31
A pointer receiver *Person lets the method change the original value. Value receivers get a copy and cannot mutate the caller.
Watch out: use a pointer receiver when the method must modify the struct.
Each one is defined here on this site. Open the entry for the full definition and the other words it points at.