Day one post about learning Go
All checks were successful
Build and copy to prod / build-and-copy (push) Successful in 2m36s
All checks were successful
Build and copy to prod / build-and-copy (push) Successful in 2m36s
This commit is contained in:
parent
500dc71c90
commit
3cb0374cda
144
src/blog/posts/2024/5/learning-go-day-1.md
Normal file
144
src/blog/posts/2024/5/learning-go-day-1.md
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
---
|
||||||
|
title: "Learning Go: Day One"
|
||||||
|
date: 2024-05-01T09:00:00.0Z
|
||||||
|
tags:
|
||||||
|
- tech
|
||||||
|
- learning
|
||||||
|
- go
|
||||||
|
excerpt: "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 with it by the end of the month."
|
||||||
|
---
|
||||||
|
|
||||||
|
I've wanted to try learning [Go](golang.org/) 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](https://www.hashicorp.com/blog/writing-custom-terraform-providers), 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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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](https://gobyexample.com). Based on the "hello world" example, I created a `main.go` file, and then was able to run it using `go run main.go`.
|
||||||
|
|
||||||
|
```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!".
|
||||||
|
|
||||||
|
```go
|
||||||
|
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:
|
||||||
|
|
||||||
|
```go
|
||||||
|
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.:
|
||||||
|
|
||||||
|
```go
|
||||||
|
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:
|
||||||
|
|
||||||
|
```go
|
||||||
|
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.Println(fmt.Sprintf("2 * 5 = %d", num))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`var num int = multiply(2, 5)` feels extremely verbose. Luckily Go does have type inference, so I can use a shorthand declaration:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
fmt.Println(sayHello())
|
||||||
|
num := multiply(2, 5)
|
||||||
|
fmt.Println(fmt.Sprintf("2 * 5 = %d", 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.
|
Loading…
Reference in New Issue
Block a user