

Disclaimer: This post includes Amazon affiliate links. Clicking on them earns me a commission and does not affect the final price.
Hello 👋 I’ve been using Go professionally since 2015. I’ve written, seen a lot of Go code, and shipped a lot of services built in Go, but I’ve also made mistakes when using Go.
Since my early beginnings, I’ve been an ambassador of the language, creating content to help other newcomers, and I’ve talked positively about the language.
I understand it is not a perfect programming language, but I’ve never talked about the things I don’t like; that will change now 🙃.
Let’s talk about three things I don’t like about the Go programming language.
Because exported variables can be replaced by anyone importing the package you should consider the following:
Default()
instead of a variable Default
.Consider a package that has the following exported variable:
3var Default = Calculator{
4 names: map[string]int{
5 "Mario": 10,
6 "Ruby": 15,
7 },
8}
And it’s being used in a Calculator
type:
20func (c Calculator) Percentage(name string) int {
21 v, ok := c.names[name]
22 if !ok {
23 return DefaultValue
24 }
25
26 return v
27}
Its default behavior could be changed by replacing the exported Default
variable:
15 bonus.Default = bonus.NewCalculator(map[string]int{"Mario": 200, "Ruby": 300})
16 bonus.DefaultValue = 500
To fix this it, my recommendation would be to replace that exported variable with a function, this way it can’t be replaced and it’s always a new instance:
3func Default() Calculator {
4 return Calculator{
5 names: map[string]int{
6 "Mario": 10,
7 "Ruby": 15,
8 },
9 }
10}
That way it won’t be able to be modified by users importing that package:
10 fmt.Println("Mario", bonus.Default().Percentage("Mario"))
11 fmt.Println("Ruby", bonus.Default().Percentage("Ruby"))
12
13 // Compiler error:
14 //-
15 // bonus.Default = bonus.NewCalculator(map[string]int{"Mario": 200, "Ruby": 300}) // because is function
16 // bonus.DefaultValue = 500 // because is constant
Test and tool dependencies are tracked in the same go.mod
; thus, downloading them is unnecessary when building a production artifact, there’s a proposal to change the way tests are tracked, and in Go 1.24 tools are already tracked in a different go.mod
section.
Let’s assume we are still using the old tools paradigm, in this case sqlcx
:
8import (
9 _ "github.com/golang-migrate/migrate/v4/cmd/migrate"
10 _ "github.com/sqlc-dev/sqlc/cmd/sqlc"
11)
That will bring those dependencies every time the binary is being built, although in practice the tool is only used for pre-build purposes.
switch
statementswitch
is a well known statement in Go, that allows grouping similar conditionals via the same expression, however this expression is not required, allowing to write programs that could abuse this statement.
What this means is, take this common switch
statement:
15 value := 10
16 switch value {
17 case 2:
18 fmt.Println("It's 2")
19 case 10:
20 fmt.Println("It's 10")
21 }
It uses value
as a way to determine what case it should match, but this expression is not enforced, allowing code like the following to still be valid:
44 switch {
45 case errors.Is(err, ErrEmpty):
46 fmt.Println("empty string")
47 case errors.Is(err, ErrTooLong):
48 fmt.Println("too long string")
49 case str == "hello":
50 fmt.Println("said hello")
51 case str == "world":
52 fmt.Println("said world")
53 case err != nil:
54 fmt.Println("other error", err)
55 default:
56 fmt.Println("value was", str)
57 }
The code above checks for two things: errors, same values; and also provides a default behavior; of course it is valid Go code but it makes harder to read when everything is cramped into a switch.
I’ve been using Go for what it looks like forever and although I have a few things I don’t like I still think is a good programming language that can be used for almost all the different use cases we see in real life as Software Engineers, understanding it and knowing the caveats and what we you shouldn’t be doing in certain cases is useful for all Go programmers.
If you’re looking to sink your teeth into more Go-related topics I recommend the following books: