Code Review in Go: What to Check and How to Give Feedback

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Code Review in Go: What to Check and How to Give Feedback



Code review is not just a formality, but a crucial stage of development. Especially in Go, where code simplicity and readability are embedded in the language's philosophy. For beginner developers, this can seem daunting: how can you criticize someone else's code when you're not even confident yourself? In reality, code review is the best way to learn. In this article, we'll break down what to look for when reviewing Go code and how to give feedback that is helpful, not hurtful.



1. Basic Principles: What to Look for First



Before diving into details, remember the main rule: the review is about the code, not the person. Your goal is to find potential problems and improve the quality of the product, not to prove you are smarter. Start with simple things:



  • Logic errors: are edge cases handled correctly? For example, what happens if the slice is empty?
  • Potential panics: did you forget about nil? Check that you are not calling methods on a nil pointer.
  • Unused code: in Go this leads to a compilation error, but sometimes dead variables or imports remain.


Example of a typical beginner mistake:



func getFirstElement(s []int) int {    return s[0] // Panic if the slice is empty!}


What to suggest in the review: add a check for the slice length and return an error.



func getFirstElement(s []int) (int, error) {    if len(s) == 0 {        return 0, fmt.Errorf("slice is empty")    }    return s[0], nil}


2. Go Idioms: How to Write "the Go Way"



Go is not Java or Python. It has its own style that should be respected. During review, pay attention to the following points:



  • Naming: in Go, short names are common (e.g., r for reader, w for writer). Don't name a variable myReader — just use r.
  • Error handling: don't ignore errors! If a function returns error, it must be checked. Exceptions are fmt.Println and similar, but even those are better logged.
  • Interfaces: they should be small. One method is good, two is already a lot. Don't create interfaces "for future use."


Example of "non-Go" code:



func ProcessData(data []string) (bool, error) {    var result bool    for _, item := range data {        if item == "error" {            result = false            return result, errors.New("found error")        }    }    result = true    return result, nil}


Here result is unnecessary — you can just return true or false directly. Also, use fmt.Errorf for formatting.



func ProcessData(data []string) (bool, error) {    for _, item := range data {        if item == "error" {            return false, fmt.Errorf("found error in item: %s", item)        }    }    return true, nil}


3. Performance and Memory: What to Look For



Although Go is quite fast, bad code can ruin everything. During review, check:



  • Avoid unnecessary allocations: if you know the size of the slice, use make with a specified capacity.
  • Copying structs: large structs are better passed by pointer to avoid copying them every time.
  • Goroutines: check that you haven't forgotten to close a channel or wait for a goroutine to finish (use sync.WaitGroup).


Example of poor slice handling:



func appendItems(items []int) []int {    var result []int    for _, v := range items {                

Blogs

Book Recommendations