Change your colour scheme

Learning Go: Day One

Published:

I’ve wanted to try learning Go for a while now, but have never got round to it. So I’m going to (attempt) to learn a little bit about it each day, and blog about it, with a view to building something[1] with it by the end of the month.

I thought it’d be a nice idea to blog through the process, mostly so I have my own record of what I’m doing.

Why Go?

A couple of reasons. I quite like compiled languages, because you get nice neat executables that don’t take up 10mb of disc space[2]. It’s also got a reputation for being pretty simple, and good for web stuff, and finally I’ve had a couple of instances where I’ve wanted to make a custom Terraform provider, but that requires knowledge of Go.

Accountability

None. There is absolutely nothing riding on this, if I stop blogging about it/learning, then so be it.

Day one: setup, packages, functions, types

The first day is pretty simple. To start with, I installed the Go CLI using brew:

brew install go

Then created a new directory to work in, aptly named learn-go.

Initialising a project

So first-things-first, how do I create a project? Running go help doesn’t give me any obvious init commands, so I search the web. It turns out a project needs a go.mod file, which is sort of equivalent to package.json in node-land, only not. To create the mod file, I just run go mod init <module name>.

Apparently it’s standard for module names to be prefixed with a namespace identifier, that’s often a domain name for uniqueness, so I just used this domain.

go mod init lewisdale.dev/learn-go

That created a go.mod file that just contained the following:

module lewisdale.dev/learn-go

go 1.22.2

Hello, world!

Alright, looks like we’re cooking now. Secondly, I looked for some tutorials online, and found a couple of useful resources, including Go by Example. Based on the “hello world” example, I created a main.go file, and then was able to run it using go run main.go.

package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}

Riveting stuff, but at least it ran!

Creating a function

Okay so technically I’ve already created a function. But that’s an entrypoint, it doesn’t count. So now I’m going to create something spectacular, I’m going to create a function that returns the string “hello, world!”.

package main

import "fmt"

func sayHello() string {
    return "Hello, world!"
}

func main() {
    fmt.Println(sayHello())
}

This actually tripped me up at first. I assumed that Go’s type inference would know that I’m returning a string, so didn’t specify a return type (that’s the string right after the brackets on line 5). But then I got a compiler error because I was trying to return from a function with no return types.

That syntax for return types is a bit weird, I quite like having a charater denote that “these are the return types”, like a :, but maybe that’s just because I’m used to it.

Variables and types

This is where the syntax gets a bit stranger. If I want to take, say, two ints, and multiply them, that’s reasonably simple to define:

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

The type comes after the variable name, rather than before like in most languages I’ve used. Odd. Also, if I have multiple arguments of the same type, I can just put the type at the end of the list, e.g.:

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

Kinda neat, could be a minor pain if you’ve got a list of arguments and you need to swap the types of just one of them, but that feels like an edge-case anyway.

Now if I want to declare a variable from my function return, I can do:

package main

import "fmt"

func sayHello() string {
    return "Hello, world!"
}

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

func main() {
    fmt.Println(sayHello())
    var num int = multiply(2, 5)
	fmt.Printf("2 * 5 = %d\n", num)
}

var num int = multiply(2, 5) feels extremely verbose. Luckily Go does have type inference, so I can use a shorthand declaration:

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

And that works! I think I’ll leave this post there for now, tomorrow I’ll probably do more with functions, and try a bit of code management.


  1. At the time of writing, “something” has yet to be decided ↩︎

  2. Looking at you, Javascript bundlers. ↩︎

Tags:

About the author

My face

I'm Lewis Dale, a software engineer and web developer based in the UK. I write about writing software, silly projects, and cycling. A lot of cycling. Too much, maybe.