This is kata to get you a taste of Go with some hands on tasks.
If anytime you are stuck you can check the docs, and specifically the standard library docs since we will try to not add other dependencies. And in case you cannot tell from where an identifier comes from it might be a builtin.
Anytime you have a doubt on a concept, be it syntax or semantic or both, the Effective Go document will probably help, keep it handy.
There are several tasks for you, none of them is very specific just let the comments in the code guide you and have fun!
If you did not set up a Go development environment this is your first task 😉. Installing instruction for the Go compiler and tools are available on the official Go website
Go may also be available as a package for your OS, e.g. on MacOS is available via brew isntall go.
Remember to check the installation was successful by typing go version in your terminal.
Go has an official Language Server, gopls, with plugins available for popular editors.
Let's compile and run a Hello World program and get familiar with the go tool.
The code for this task is in the task-1 directory.
💡Here is a list of things you may want to try:
- open
main.goin your editor and have a look around - run
go run . - run
go run main.go - run
go buildto compile thehellocommand, check the directory afterward and run your new executable - run
go envto see all the go environment variables - run
go helpto see more go sub-commands, there are a few so you might want to use a pager
Now that we have some basic familiarity with the go tool it is time for some tests!
Go provides a testing package in the standard library and it is integrated with the go tool making it a quite comprehensive testing framework.
The canonical way of testing go packages is to run go test in a directory containing a package, or run go test ./... in the root directory of a module to run all the test in the module.
💡Is there something wrong with the address package in the task-2 directory?
Can you improve the code and write some more test?
Can you check the test coverage?
Some tips:
- from the root directory of this repository try to run
go test ./...to test the whole module - from the root directory of this repository try to run
go test ./task-2to test only the package in that directory - cd into the
task-2directory and rungo test - run
go help test - run
go test -json
Test coverage is also included (as are benchmarking and fuzzing) and works out of the box, try some of these commands
- run
go help testflag - run
go test -coverprofile=coverage.out - run
go tool cover -func=coverage.out - run
go tool cover -html=coverage.out - see the whole cover story at go.dev/blog/cover
This task will make you familiarize with how Go avoid inheritance in favor of composition. Another interesting feature of Go is the structural sub-typing that interfaces provide, along with the Liskov substitution.
With your help we want to build an online shop to make Jeff green with envy!
I this task we are going to use the Address from task-2 and provide our Users with a billing and shipping address.
Also we need our users to be able to login, maybe we can use and interface to delegate the actual logic to different specific implementations.
Some tips:
Given a Count type:
type Count struct{
Value int
}
func(c *Count) Inc(){
c.Value +=1
}We can embed it in another type:
type Foo struct {
Bar string
Count
}The embedding type will have the methods of the embedded:
f := Foo{
Bar: "Bar",
// Count is created with its zero-value
}
f.Inc() // now f.Count.Value == 1
fmt.Println(f.Value) // we can skip to the inner values of the embedded typeEmbedding can be done with Interfaces as well, when we create a type embedding an interface we need to provide a type implementing that interface.
type Baz struct {
Qux string
io.Writer // this is an embedded interface
}
b := Baz{
Qux: "Qux",
Writer: bytes.NewBuffer([]byte{'H','e','l','l','o'}), // bytes.Buffer implements io.Writer
}In this task we are going to play around with a small web server, the web server is not accomplishing much yet but it will be useful to show some nice Go features.
💡Things to do:
- cd into
cmd/task-4 - you should know by now how to compile and run the code ;)
- have a look at the
middlewares.gofile, can you improve the log middleware as the comments mentioned?
David Attenborough voice Ah the fabled Goroutines... not system threads and nor coroutines, more like a flock of concurrent subroutines multiplexed on a pool of system threads...
Go has a concurrency model not based on async await but based on CSP.
The CSP model(Commicating Sequential Processes) was devised by Tony Hoare ~50 years ago.
The same Tony Hoare is the one that admitted to the "billion dollar mistake" by introducing NULL pointers.
The irony of Go having null pointers is not wasted on me...
Back to the goroutines, to start a goroutine prepend the go keyword to a function invocation:
func DoThings(){
// things are done here...
}
go DoThings() // the function runs concurrentlyAny function can run concurrently, no coloring needed.
But goroutines cannot return any value, luckily we can avoid the headaches of conditions and semaphores by using channels as in CSP.
The Go proverb for this is Do not communicate by sharing memory; instead, share memory by communicating.
func DoThings(resultChan chan string){
// things are done here...
// and the result sent via the channel
resultChan <- "result of a loooong computation"
}
ch := make(chan string)
go DoThings(ch) // run concurrently
res := <- ch // block execution waiting to receive from channelWhen you have to coordinate I/O from more channels the select comes in to help.
It is basically a switch but each case is a channel receive or send:
select{
case a := <- chanA:
// do stuff with a
case chanB <- data:
// if chanB is ready send data
default:
// do this in case all channels are not ready
}Cross compile in Go is as simple as setting GOOS and GOARCH and running go build.
To try it out is better to see the available values in you Go installation.
Run go tool dist list to see them all.
💡Try to build a binary for another OS or CPU architecture!
💡It's Beer o'clock!