# 100 Go Mistakes and How to Avoid Them ![rw-book-cover](https://readwise-assets.s3.amazonaws.com/media/reader/parsed_document_assets/461752136/qWSmYH7YdhRwQ-qVCIi6mHsJ7rsv_ECK3S_0C0g5oYk-cover-cover.jpeg) ## Metadata - Author: [[Teiva Harsanyi]] - Full Title: 100 Go Mistakes and How to Avoid Them - Category: #books - Summary: Go developers often confuse slice length and capacity, which can cause inefficient code or memory issues. Data races happen when multiple goroutines access the same memory simultaneously, causing unpredictable results. Understanding memory allocation on the stack and heap is key for writing efficient and safe Go programs. ## Highlights ### 1 Go: Simple to learn but hard to master - Making mistakes is part of everyone’s life. As Albert Einstein once said, A person who never made a mistake never tried anything new. ([View Highlight](https://read.readwise.io/read/01kwnmjvk3zhcs9fjf749kcmxt)) #### 1.1 Go outline - Nowadays, code must be readable, expressive, and maintainable to guarantee a system’s durability over the years. ([View Highlight](https://read.readwise.io/read/01kwnmkrhmavp6bc2aj0b4nc6v)) - Google created the Go programming language in 2007 ([View Highlight](https://read.readwise.io/read/01kwnmmdrxqe67zxhs1rskg989)) - Many today consider Go the language of the cloud. ([View Highlight](https://read.readwise.io/read/01kwnmmv5yw8zgbt1chvw7e92b)) - *Stability*—Even though Go receives frequent updates (including improvements and security patches), it remains a stable language. Some may even consider this one of the best features of the language. ([View Highlight](https://read.readwise.io/read/01kwnmnwpbp4bbh4f54j63j3hq)) - *Expressivity*—We can define expressivity in a programming language by how naturally and intuitively we can write and read code. A reduced number of keywords and limited ways to solve common problems make Go an expressive language for large codebases. ([View Highlight](https://read.readwise.io/read/01kwnmp474kg4mqr182ew5jw1m)) - *Compilation*—As developers, what can be more exasperating than having to wait for a build to test our application? Targeting fast compilation times has always been a conscious goal for the language designers. This, in turn, enables productivity. ([View Highlight](https://read.readwise.io/read/01kwnms88716zasmaf4vwk4asa)) - *Safety*—Go is a strong, statically typed language. Hence, it has strict compile-time rules, which ensure the code is type-safe in most cases. ([View Highlight](https://read.readwise.io/read/01kwnmsc0bav9tznvhk78t169y)) - Go was built from the ground up with solid features such as outstanding concurrency primitives with goroutines and channels. There’s not a strong need to rely on external libraries to build efficient concurrent applications. ([View Highlight](https://read.readwise.io/read/01kwnmy65fxc8v9gpsek0fbjb9)) #### 1.2 Simple doesn’t mean easy - In 2019, a study focusing on concurrency bugs was published: “Understanding Real-World Concurrency Bugs in Go.”[1](#pgfId-1121786) This study was the first systematic analysis of concurrency bugs. It focused on multiple popular Go repositories such as Docker, gRPC, and Kubernetes. One of the most important takeaways from this study is that most of the blocking bugs are caused by inaccurate use of the message-passing paradigm via channels, despite the belief that message passing is easier to handle and less error-prone than sharing memory. ([View Highlight](https://read.readwise.io/read/01kwnn0vc6jjkgyexsdjm3y826)) #### 1.3 100 Go mistakes - Tell me and I forget. Teach me and I remember. Involve me and I learn. —Unknown ([View Highlight](https://read.readwise.io/read/01kwnnzfe0h2m9c9yht85zggc7)) - This book presents seven main categories of mistakes. Overall, the mistakes can be classified as • Bugs • Needless complexity • Weaker readability • Suboptimal or unidiomatic organization • Lack of API convenience • Under-optimized code • Lack of productivity ([View Highlight](https://read.readwise.io/read/01kwnp020cr7nznmf1mdsv0d36)) ##### 1.3.1 Bugs - Furthermore, bugs can also lead to tragic impacts. We can, for example, mention cases such as Therac-25, a radiation therapy machine produced by Atomic Energy of Canada Limited (AECL). Because of a race condition, the machine gave its patients radiation doses that were hundreds of times greater than expected, leading to the death of three patients. Hence, software bugs aren’t only about money. As developers, we should remember how impactful our jobs are. ([View Highlight](https://read.readwise.io/read/01kwnp10a46arbzxbm0egp4q2b)) ### 2 Code and project organization - 2.1 #1: Unintended variable shadowing ([View Highlight](https://read.readwise.io/read/01kwnqtffr4b92cjdpakw6tgqj)) #### 2.1 #1: Unintended variable shadowing - var client *http.Client ❶ if tracing { client, err := createClientWithTracing() ❷ if err != nil { return err } log.Println(client) } else { client, err := createDefaultClient() ❸ if err != nil { return err } log.Println(client) } // Use client ([View Highlight](https://read.readwise.io/read/01kwnqtjmj459776wm389m56d9)) - In this example, we first declare a `client` variable. Then, we use the short variable declaration operator (`:=`) in both inner blocks to assign the result of the function call to the inner `client` variables—not the outer one. As a result, the outer variable is always `nil`. ([View Highlight](https://read.readwise.io/read/01kwnqtw51d5c6cmvqf79v0jxd)) - How can we ensure that a value is assigned to the original `client` variable? There are two different options. ([View Highlight](https://read.readwise.io/read/01kwnr7ff2spdj63s75s0y23b6)) - The first option uses temporary variables in the inner blocks this way: var client *http.Client if tracing { c, err := createClientWithTracing() ❶ if err != nil { return err } client = c ❷ } else { // Same logic } ([View Highlight](https://read.readwise.io/read/01kwnr7my6btz0384wzcaesspj)) - The second option uses the assignment operator (`=`) in the inner blocks to directly assign the function results to the `client` variable. However, this requires creating an `error` variable because the assignment operator works only if a variable name has already been declared. For example: var client *http.Client var err error ❶ if tracing { client, err = createClientWithTracing() ❷ if err != nil { return err } } else { // Same logic } ([View Highlight](https://read.readwise.io/read/01kwnraz4qf83nh2chcm63h920)) - Also, with the second option, we can mutualize and implement error handling outside the `if`/`else` statements, as this example shows: if tracing { client, err = createClientWithTracing() } else { client, err = createDefaultClient() } if err != nil { // Common error handling } ([View Highlight](https://read.readwise.io/read/01kwq8jb1z13717y82d3ea726y)) - Variable shadowing occurs when a variable name is redeclared in an inner block, but we saw that this practice is prone to mistakes. ([View Highlight](https://read.readwise.io/read/01kwq8rnh2s4kvk3fjw9kqmrdp)) - Imposing a rule to forbid shadowed variables depends on personal taste. For example, sometimes it can be convenient to reuse an existing variable name like `err` for errors. Yet, in general, we should remain cautious because we now know that we can face a scenario where the code compiles, but the variable that receives the value is not the one expected. ([View Highlight](https://read.readwise.io/read/01kwq8sa8f67qq7jm3pmwch8vq))