---
title: "Learning Go: Day Two"
date: 2024-05-02T08:00:00.0Z
tags:
    - learning
    - go
excerpt: "In part two, I take a look at how to organise code into packages"
---

Welcome to Part Two of my series on Learning Go for WeblogPoMo. In this part, I'm going to look at how to organise my code into separate packages, so that I don't have to store everything in once single file.

## Creating a package

This was fairly straightforward. Packages are noted by the `package <name>` directive at the start of the file. You can even see that in `main.go`, which has `package.main` at the start. So, to create a package I added a directory for it (I'm calling it `maths`[^1]), and then added a `maths.go` file to it. For now, I'll just move the `multiply` function to it:

```go
package maths

func multiply(a, b int) int {
	return a * b
}
```

Fairly straightforward, right?

## Importing and running the code

So, I can't just do `import "maths"`, because that doesn't seem to resolve. Instead, I have to refer to my entire module name, and then append the path to it:

```go
import "lewisdale.dev/learn-go/maths"
```

So now I should be able to use my imported module and call `maths.multiply`, right?

```go
func main() {
	fmt.Println(sayHello())
	num := maths.multiply(2, 5)
	fmt.Printf("2 * 5 = %d\n", num)
}
```

```bash
go run main.go
> ./main.go:16:15: undefined: maths.multiply
```

## Wait, what?

So, it turns out in Go, there's no explicit export keyword. Instead, if you want a function to be exported [you have to capitalise the first letter](https://go.dev/tour/basics/3). Lowercase functions are implicitly private.

```go
// maths.go
package maths

func Multiply(a, b int) int {
	return a * b
}
```

And then we can do

```go
// main.go
func main() {
	fmt.Println(sayHello())
	num := maths.Multiply(2, 5)
	fmt.Printf("2 * 5 = %d\n", num)
}
```

As a useful extra, the Go plugin on VS Code[^2] even organised my imports into one `import ()` statement:

```go
// main.go
package main

import (
	"fmt"

	"lewisdale.dev/learn-go/maths"
)
```

## The vendor directory

When I was looking up how to create and import modules, I did find [this useful StackOverflow comment](https://stackoverflow.com/a/45813698) that mentions that Go > 1.5 has support for a `vendor` directory, that allows you to put code inside a `vendor` directory, and Go will lookup the package without requiring the local module prefix.

I'm not going to use this, just because I'm probably going to reinvent the wheel a few times over the course of this series and I don't know the standard library well enough[^3] to trust myself to not accidentally tread all over it, but it's good to know it's there.

[^1]: Yes, maths, not math
[^2]: It was less helpful when it kept auto-deleting my import before I did the export though, had to use Vim just to make my point.
[^3]: Or like, at all.