References
Introduction
Moving onto structs now.
Basically a way to collect related data. Here is the example,
type car struct {
brand string
model string
doors int
mileage int
}Structs can be nested. Example,
type car struct {
brand string
model string
doors int
mileage int
frontWheel wheel
backWheel wheel
}
type wheel struct {
radius int
material string
}What is interesting about the above is that we did not need to define wheel before car. Looks like it’s fine as long as it’s within the same scope?
Something interesting is how to access data in a nested struct. Or I guess, a regular struct - using the dot . operator. Example,
myCar := car{}
myCar.frontWheel.radius = 5In the above, I find the default assignment of car{} very interesting. I do not think I’ve seen similar before.
This is interesting. I cannot convert string to bool directly in golang.
This is a weird one. golang has the concept of anonymous structs. Here is the example they use and IMO, the re-declaration during instantiation looks cumbersome,
type car struct {
brand string
model string
doors int
mileage int
// wheel is a field containing an anonymous struct
wheel struct {
radius int
material string
}
}
var myCar = car{
brand: "Rezvani",
model: "Vengeance",
doors: 4,
mileage: 35000,
wheel: struct {
radius int
material string
}{
radius: 35,
material: "alloy",
},
}This is surprising to me - golang is NOT an object oriented language!
Go has the notion of embedded structs. This is … a head-scratcher for me. It allows the embedded struct’s fields to be accessed at the top level like other fields, instead of via the imported one. This code below demonstrates things,
// some struct definitions
type car struct {
brand string
model string
}
type truck struct {
// "car" is embedded, so the definition of a
// "truck" now also additionally contains all
// of the fields of the car struct
car
bedSize int
}
// using them,
lanesTruck := truck{
bedSize: 10,
car: car{
brand: "Toyota",
model: "Tundra",
},
}
fmt.Println(lanesTruck.brand) // Toyota
fmt.Println(lanesTruck.model) // Tundra
My coding instincts tell that this should cause problems. But since it is a part of the language - there must be something I’m not seeing here.
Oh. When use embedded structs - there is not variable name assigned for the embedded data. So we can’t use composition-like access. It makes sense, but I’m not satisfied.
As if things weren’t confusing enough, golang has the notion of struct methods. These are defined using receivers. Here is some code example,
type rect struct {
width int
height int
}
// area has a receiver of (r rect)
// rect is the struct
// r is the placeholder
func (r rect) area() int {
return r.width * r.height
}
var r = rect{
width: 5,
height: 10,
}
fmt.Println(r.area())
// prints 50Format a string without printing,
Use fmt.Sprintf() to do this.
A thing about golang structs is that they are stored as contigous blocks in memory. The can lead to wasted space - but in general usage it should not matter.
If you want to make it matter, ordering variables from largest to smallest can help. There are packages in go to help figure this out. (not looking them up now!)
There is a thing called “empty structs”. Code,
// anonymous empty struct type
empty := struct{}{}
// named empty struct type
type emptyStruct struct{}
empty := emptyStruct{}These are used as unary values.
This is surprising to me. We need lots of commas when instantiating a struct.
Just submitted this as part of an exercise,
func (u User) SendMessage(message string, messageLength int) (string, bool) {
if messageLength <= u.MessageCharLimit {
return message, true
}
return "", false
}
// don't touch below this line
type User struct {
Name string
Membership
}
type Membership struct {
Type string
MessageCharLimit int
}The return type definitions in that function … are something I need to get used to.