Skip to content

Latest commit

 

History

History
257 lines (192 loc) · 5.45 KB

File metadata and controls

257 lines (192 loc) · 5.45 KB

Structs

In this chapter, we will learn about structs. A struct is a complex data type capable of holding many fields. It can also be extended to hold behaviour.

Introduction

This chapter will cover:

  • Declaring and inspecting a struct.
  • Embedding a struct within another struct.
  • Adding implementations to structs.

Why structs

Let's start with a simple scenario, you have an account balance. You might store it in a variable like so:

accountBalance int32

Now that's great, but if you want to describe something more complex, like a bank account? A bank account consists of a variety of information like an ID, balance, account owner and so on. You could try representing each one of those properties as integers like so:

var accountBalance int32
var owner string
var id int

However, what happens if you need to operate on more than one bank account, I mean you could try to store it like so:

var accountBalance int32
var owner string
var id int

var accountBalance2 int32
var owner2 string
var id2 int

It doesn't scale though, what you need is a more complex type, like a struct that's able to group all this information like so:

type Account struct {
  accountBalance int32
  owner string
  id int
}

Defining a struct

Ok, so we understand why we need a struct, to gather related information, and we've seen one example so far Account. But let's try breaking the parts down and see how we go about defining a struct. Here's what the syntax looks like:

type <a name for the struct> struct {
  ... fields
}

Let's show another example but this time we create a struct for an address:

type Address struct {
 city   string
 street string
 postal string
}

Create a struct instance

To create an instance from a struct, we can use one of two approaches:

  • define a variable, and set the fields after the variable declaration:

    var address Address
    address.city = "London"
    address.street = "Buckingham palace"
    address.postal = "SW1"
  • define all at once, we can set all the values in one go as well:

    address2 := Address{"New York", "Central park", "111"}

Embedding a struct

We can also embed a struct in another struct. Let's see we have our Address struct, an address is something that a higher level struct like Person can use. Here's how that can look:

type Person struct {
 name    string
 address Address
}

In this code, the Person struct has a field address of type Address.

To instantiate a struct, we can type like so:

person := Person{
  name: "chris",
  address: Address{
   city: "Stockholm",
  },
 }

Relying on default naming

Note how we created a field address, we can skip typing a few characters by defining it like so instead:

type Employee struct {
 Address
 company string
}

Note how we omit the name for the field and just type Address, this means the field name and field type will be the same name. Creating an instance from it is similar:

employee := Employee{
  Address: Address{
   city: "LA",
  },
  company: "Microsoft",
 }

Adding implementation to structs

Structs are by their very nature just data fields that describe something complex. You can add behaviour to it though by creating functions that operate on a struct. Here's an example:

func (a Address) string() string {
 return fmt.Sprintf("City: %s, Street: %s, Postal address: %s", a.city, a.street, a.postal)
}

We've added a string() method. The method belongs to Address and we can see that with (...) right after the func keyword that takes a Address. The rest of the implementation returns a formatted string via Sprintf(). Given the following code:

var address Address
address.city = "London"
address.street = "Buckingham palace"
address.postal = "SW1"
fmt.Println(address.string())

We would get the following output when calling string():

City: London, Street: Buckingham palace, Postal address: SW1

Assignment - defining a struct

Define a struct representing a row in a shopping basket for an e-commerce store.

Here's example data:

Title, Description, Quantity, Price per unit, Total
LEGO set, 4000 pieces, 1, 600GBP, 600GBP 

Write a program representing the shopping basket

Write a program that iterates over the shopping basket and calculates the total:

Title, Description, Quantity, Price per unit, Total
LEGO set, 4000 pieces, 1, 600GBP, 600GBP
Plushy, plush toy, 3, 5 GBP, 15GBP 

Total: 615 GBP

Solution

Part I

package main

import (
 "fmt"
)

type Row struct {
 Title       string
 Description string
 Quantity    int
 UnitPrice   float32
}

func main() {
 row := Row{
  Title:       "LEGO set",
  Description: "4000 pieces",
  Quantity:    1,
  UnitPrice:   600,
 }
 fmt.Println(row)
}

Part II

package main

import (
 "fmt"
)

type Row struct {
 Title       string
 Description string
 Quantity    int
 UnitPrice   float32
}

func main() {
 row := Row{
  Title:       "LEGO set",
  Description: "4000 pieces",
  Quantity:    1,
  UnitPrice:   600,
 }
 row2 := Row{
  Title:       "Plushy",
  Description: "plush toy",
  Quantity:    3,
  UnitPrice:   5,
 }

 basket := make([]Row, 0)
 basket = append(basket, row)
 basket = append(basket, row2)

 var sum int = 0
 for i := 0; i < len(basket); i++ {
  current := basket[i]
  fmt.Println(current)
  sum += current.Quantity * int(current.UnitPrice)
 }
 fmt.Println("Total", sum)
}