Learning a new programming language can be quite daunting.
Existing Python programmers might feel overwhelmed when starting to contribute in a new language.
Some of the early contributors to this project were also new to Go. This document offers some pointers on how to learn the language effectively in relation to this project.
As your first point of contact, you can experiment with Go in the browser via the "A Tour of Go" interactive application. This tour is translated into several languages beyond English and covers some basics.
The Tour of Go focuses on syntax but lacks real-world experience. Learning a new language involves not just the syntax but also understanding the toolchain and ecosystem. Therefore, we recommend Learn Go with Tests. This guide teaches you Go in a way that closely resembles how coding in Go will look in this project.
Lastly, if you prefer to learn through video materials, we recommend Learn Go Fast: Full Tutorial. This is a straightforward walkthrough of all the concepts in Go.
Depending on the languages you've used in the past, Go might be a bit different for you.
Don't try to fight this! Before I worked on this project, I was doing functional programming. While Go allows you to pass functions as arguments, many concepts operate in an imperative way. The advice here is to avoid merely translating syntax from languages with other paradigms. Instead, try to solve problems "the Go way" and let go (pun intended) of your past experiences.
It's perfectly fine if you've never installed Go before! To make things easier, we've provided a dev container for everyone to use.
Using the dev container ensures you have the correct version of Go, along with the linters, editor plugins, and various other tools you might need for this project. It keeps your operating system clean and provides a consistent contributor experience.
We make heavy use of golangci-lint in this project. This ensures code quality and consistency among various contributors. It’s a blessing for newcomers, as it can highlight honest mistakes you may be unaware of.
We use multiple linters for different languages via pre-commit. Before you commit your code, you can run
pre-commit
to ensure everything is in good shape.
If this happens, please run
golangci-lint cache clean
We expect this issue to be resolved in future Go lint releases.
Unit tests can be a great way to quickly test something in Go. If you want to explore some temporary code, you can add a temporary unit test to one of the existing _test.go
files.
func TestSomethingNew(t *testing.T) {
t.Error("Failing test!")
}
go test -run ^TestSomethingNew$ ./pkg/tracking/service/query/lexer/tokenizer_test.go
In addition to learning Go, it can be beneficial to familiarize yourself with some of the Go libraries used in this project.
While vanilla Go includes a basic web routing framework, it proved to be too limiting for our needs. We utilize Fiber to serve static files and API routes for the tracking server.
Most of our Fiber code is generated (e.g., pkg/server/routes/tracking.g.go), but it may still be worthwhile to understand the generated code.
As mentioned earlier, we generate a considerable amount of code from the *.proto
files of mlflow
. (See magefiles/generate.go). We use the standard go/parser and go/ast packages to parse Go source code generated by protoc
and modify the abstract syntax tree (AST) to suit our requirements.
A helpful tool for inspecting the Go AST is https://astexplorer.net/.
We validate all incoming request structs using the Go validator package.
As explained in our guide for porting a new endpoint, we don't add tags to the struct directly; instead, we configure them in magefiles/generate/validations.go.
Run
mage generate
after making any changes.
We use Gorm as our Object Relational Mapper (ORM) to communicate with any SQL instance.
Please note that we do not have any migrations in Go and cannot construct a new database; this process still occurs in Python.