5 Things to unlearn when learning Go

Dylan Meeus
3 min readNov 3, 2019
Photo by Manan Chhabra on Unsplash

Learning Go has been a fun journey, and when you’re used to writing a mainstream language such as Java or C# the learning curve isn’t that steep. But there are some things I had to actively unlearn when learning Go. Most of the things here are not harmful to your code at all, and the code functions pretty much as intended anyway. The compiler will not come shouting at you, so perhaps the worst that could happen would be a nitpick comment on a code review. 😃

Breaking switch

Switch statements in Go don’t require break statements. This is one of the things that, purely out of habit, I kept doing for a long time. Adding them won’t actually break anything though! In Go, your switches should look like this:

func f(s string) {
switch s {
case "hello":
fmt.Println("Hello World")
case "hola":
fmt.Println("hola Mundo!")
default:
fmt.Println("'sup")
}

Prefixing Getters

In Go you will probably not use Getters that often, but when you do need them it’s tempting to prefix them with the word get such as getName(), getAge(), etc..
Doing this is not directly harmful but it is considered to be non-idiomatic Go code. For some information on what Idiomatic code would look like, check out Effective Go.

Instead, it looks like this:

type person struct {
name string
age int
}
func (p person) Name() string {
return p.name
)
func (p person) Age() int {
return p.age
}

Checking slices against nil

In Java you often deal with collection types such as ArrayList<T> or TreeSet<T>. Since these are normal objects, they can be null. Thus, in these kind of languages it makes perfect sense to write code such as

public Int GetFirst(ArrayList<Integer> arr) {
if (arr == null || arr.Length() == 0 {
return -1
}
}

However, in Go you can just check slices against their length, even when they are nil-slices. They’ll just have length zero. (You can run this example on the playground)

func main() {
var s []int
if len(s) == 0{
fmt.Println("nil!")
}
if s == nil {
fmt.Println("Yup, it's definitely nil")
}
}

Subdividing packages

Package structure in Go is something.. different. Again, in Java you end up subdividing your packages quite a bit. Encountering a package with 10 files might be strange, but more than 10 and you’d get the feeling the package should be divided more. In Go, seeing many files in a single package is not strange at all, net/http has about 50 files in it.

The package structure in Go just isn’t the same as Java, and you have to keep it in mind. Cyclical imports can cause many headaches if you do it carelessly in Go.

Making test packages

Another one that I’ve encountered ‘in the wild’ is the creation of packages just for storing test files. In java this is quite common, you’d encounter a src/ package with java code and a test/ package that contains the unit testing code. Though in Go, you’d just store your test files together with the other files for your package. This also enables the test files to access the ‘package private’ functions and structs, so you can test these. Which is fine if you’re doing “white-box testing”. Again, the earlier net/http package is a good example of this.

Thus in Go you’d get a structure such as:

pkg/
billing/
calculator.go
calculator_test.go
stripe.go
stripe_test.go

📝 Read this story later in Journal.

👩‍💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.

--

--