lewisdale.dev/src/blog/posts/2024/5/learning-go-day-2.md
Lewis Dale b29dca1648
All checks were successful
Build and copy to prod / build-and-copy (push) Successful in 2m7s
Revert restructuring the learning go titles
2024-05-01 10:01:13 +01:00

2.8 KiB

title date tags excerpt
Learning Go: Day Two 2024-05-02T08:00:00.0Z
learning
go
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 maths1), and then added a maths.go file to it. For now, I'll just move the multiply function to it:

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:

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

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

func main() {
	fmt.Println(sayHello())
	num := maths.multiply(2, 5)
	fmt.Printf("2 * 5 = %d\n", num)
}
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. Lowercase functions are implicitly private.

// maths.go
package maths

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

And then we can do

// 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 Code2 even organised my imports into one import () statement:

// 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 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 enough3 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. ↩︎