---
title: "Learning Go: Day Four"
date: 2024-05-04T08:00:00.0Z
tags:
    - learning
    - go
excerpt: "Day Four brings the joys of arrays and structs"
---

We're onto some more complex data structures today: arrays, and structs. I've skipped a couple of sections on the [Tour of Go](https://go.dev/tour) that I'm working through as part of this, but I'll double back to them later (at the time of writing, I don't fully understand what the `defer` statement is used for).

## Structs

These are pretty familar to me, purely because I've dabbled in C every now and again. Structs are almost like a precursor to objects, they're custom data types that can be defined and then referred to as argument or return types:

```go
type Date struct {
    Day int
    Month int
    Year int
}

today := Date{4, 5, 2024}
```

You can also explicity declare the struct fields:

```go
tomorrow := Date{Day: 5, Month: 5, Year: 2024}
```

Seems simple enough, no dragons there yet as far as I can tell[^1].

## Arrays

Everybody loves a good list. There are massive social media companies whose entire existence is based on lists. So naturally, I want to learn how to use and array. Instantiating an array is fairly straightforward:

```go
var nums [10]int
nums[0] = 1
nums[1] = 2
```

Alternatively you can explicity assign every value:

```go
nums := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
```

One thing that's slightly different about arrays in Go compared to how they work in languages like Javascript is that they're statically-sized. If you create an array of 10 items, you can only put 10 items in there, you can't just push an 11th item on.

## Array slices

So this is where arrays become a bit more powerful (and slightly convoluted). A slice is a reference to part of an array. They're created similarly to selecting a slice of an array in Python, by using the `array[from:to]` syntax with the start and end indexes you want to :


```go
nums := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

slice := nums[1:5]
```

Now `slice` contains the values `2, 3, 4, 5` - except they're not the values, it's just a `reference` to the values. So if I do `slice[0] = 4`, `nums[1]` will also change:

```go
nums := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

slice := nums[1:5]

slice[0] = 4;
fmt.Println(nums)

// Prints: [1 4 3 4 5 6 7 8 9 10]
```

Also, similarly to Python, you can omit either - or both - of the index range values and Go will default:

```go
nums := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

first_five := nums[:5] // {1, 2, 3, 4, 5}
tail := nums[1:] // {2, 3, 4, 5, 6, 7, 8, 9, 10}
whole_slice := nums[:] // {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
```

### Resizing slices

Slices are how we get dynamically-resizable arrays in Go, it seems. Provided the underlying array has the capacity, you can extend or shrink a slice:

```go
nums := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

slice := nums[1:5] // {2, 3, 4, 5}
slice = slice[:8] // {2, 3, 4, 5, 6, 7, 8, 9}
slice = slice[1:] // {3, 4, 5, 6, 7, 8 9}
```

And finally, Go provides some nice helper functions for slices that mean we can effectively create dyanmic arrays. The `make` function creates a slice with a given length and/or capacity:

```go
dynamic_array := make([]int, 5) // [0, 0, 0, 0, 0]
empty_array := make([]int, 0, 5) // []
```

And then `append` can be used to add a value to the slice:

```go
dynamic_array := make([]int, 0) // []

dynamic_array = append(dynamic_array, 1) // [1]
```

## Thoughts on Go so far

So far, Go seems good! The syntax is pretty clean, most of the concepts I've come across are fairly familiar on account of having used other low-level languages like C and Rust[^2]. Arrays seem a little bit more complicated than I've been used to, but as far as I can tell using slices in most places should be fine.

I'm sure I'll hit some rocky patches soon enough, as I'm still only covering the absolute basics, but I'm enjoying it nonetheless.

[^1]: Famous last words
[^2]: Not to be confused with C. Robert Cargill's Sea of Rust