This document outlines best practices and coding conventions for Go (Golang), aiming to foster code that is clean, readable, maintainable, and idiomatic to the Go programming language.
/// admonition | type: abstract Foundational Code Standards{:target="_blank"} provide the foundation, this guide extends them for Go. /// //: # (@formatter:on)
While our foundational formatting standards provide comprehensive formatting
guidelines, you should also use gofmt
to ensure consistency across all Go code.
- Indentation:
gofmt
uses tabs for indentation. Do not use spaces. - Line Length: Aim for 100 characters, but allow flexibility for readability.
- Braces: Opening braces are placed on the same line.
- Blank Lines: Use 1 line to separate code sections.
- Alignment: Align elements in documentation comments and parameter lists.
Adhere to the foundational naming conventions:
- PascalCase for classes, protocols, and enumeration types
- camelCase for methods, variables, and properties.
- Prefix booleans with
is
orhas
for clarity.
- Prefix booleans with
- UPPER_SNAKE_CASE for constants.
- lowercase package names, concatenated words (avoid underscores).
In addition, adhere to Go's naming convention recommendations:
- Local Variables: Short, but descriptive names. Single letter names are common for small scopes
- Acronyms: Keep acronyms in uppercase. For example, use
HTTPRequest
instead ofHttpRequest
. - Exported Identifiers: Start with an uppercase letter to make them public.
- Receiver Names: Keep receiver variable names short and consistent across methods.
Godoc comments should precede package and public declarations. They should be complete sentences that describe the purpose and usage of the package or identifier.
// Package goatyacademy offers a collection of tutorials and exercises for goats
// learning programming. It includes lessons on Go basics, debugging techniques,
// and advanced concepts like concurrency. Exported functions support interactive
// learning and progress tracking.
Inline comments should be used sparingly, only when necessary to explain complex logic or decisions that aren't obvious.
- Consider using tools like Swagger to generate API documentation if your Go program exposes functionalities through an API.
- This documentation should clearly explain API endpoints, request parameters, response formats, and error handling mechanisms.
Use pointers to modify an original value or to avoid copying large structures. However, use them judiciously as they can complicate the code's understanding.
package main
import "fmt"
// Goat represents a character in the game.
type Goat struct {
Name string
Score int
}
// IncreaseScore increases the score of a Goat by the given number of points.
// The Goat's score is modified in place using a pointer receiver.
func IncreaseScore(g *Goat, points int) {
g.Score += points
}
func main() {
billy := Goat{Name: "Billy", Score: 10}
IncreaseScore(&billy, 5) // Demonstrates how to use a pointer receiver to modify a struct's field.
fmt.Printf("%s's new score: %d\n", billy.Name, billy.Score)
}
Embrace Go's concurrency model using goroutines and channels for parallel execution paths. Keep synchronization and data sharing simple to maintain readability and performance.
package main
import (
"fmt"
"time"
)
// sendMessage simulates sending a message through a channel.
func sendMessage(ch chan<- string, message string) {
time.Sleep(2 * time.Second) // Simulate delay.
ch <- message
}
func main() {
messageChannel := make(chan string)
go sendMessage(messageChannel, "Lesson 1 completed")
message := <-messageChannel
fmt.Println("Received:", message)
}
Define small, focused interfaces, preferably with one or two methods. This approach promotes modular design and flexible integration of components.
package main
import "fmt"
// Edible defines behavior for food items that can be consumed by goats.
type Edible interface {
Eat()
}
// Hay is a type of food that can be eaten by goats.
type Hay struct{}
func (h Hay) Eat() {
fmt.Println("Hay is being eaten.")
}
// Treat is another type of food for goats.
type Treat struct{}
func (t Treat) Eat() {
fmt.Println("Treat is being eaten.")
}
func feedGoat(e Edible) {
e.Eat()
}
func main() {
hay := Hay{}
treat := Treat{}
feedGoat(hay)
feedGoat(treat)
}
- The
defer
statement allows you to execute a function after the surrounding function finishes ( regardless of normal execution or errors). Utilizedefer
to ensure resources are properly closed or cleanup tasks are performed even if errors occur.
Example:
package main
import (
"fmt"
"os"
)
// processOrder simulates processing an order and uses defer for cleanup.
func processOrder(filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close() // Ensure the file is closed even if an error occurs.
// Process the order here.
fmt.Println("Processing order from", filename)
return nil
}
func main() {
err := processOrder("order.txt")
if err != nil {
fmt.Println("Error:", err)
}
}
- Go offers slices (dynamically sized arrays) and maps (key-value pairs) for efficient data storage and retrieval. Utilize slices to manage collections of goats within your herd and maps for storing goat attributes that might not be common to all (e.g., favorite toys).
package main
import "fmt"
func main() {
// Slice of goat names attending the disco.
goatNames := []string{"Billy", "Daisy", "Ginny"}
// Map to store each goat's favorite dance move.
favoriteMoves := map[string]string{
"Billy": "Twist",
"Daisy": "Shuffle",
"Ginny": "Spin",
}
for _, name := range goatNames {
fmt.Printf("%s's favorite move: %s\n", name, favoriteMoves[name])
}
}
- Go Toolchain The Go toolchain, including the
go
command, is essential for compiling, running, and testing your Go programs. - GoLand: A commercial IDE by JetBrains specifically designed for Go development. It offers advanced features like code completion, refactoring, debugging, and integration with various testing frameworks.
- Visual Studio Code (VS Code): A free, open-source code editor by Microsoft with extensive customization options and support for various programming languages, including Go. You can install extensions like Go extension pack to enhance Go development functionalities within VS Code.
- Staticcheck is a static analysis tool that helps you write better Go code by flagging errors, bugs, stylistic issues, and simplifications.
- Effective Go: Offers tips for writing clear, idiomatic Go code.
- Go Code Review Comments: A collection of common comments made during reviews of Go code.