|
| 1 | +# Writing idiomatic, effective, and clean Go code |
| 2 | + |
| 3 | +Writing idiomatic, effective, and clean Go code involves adhering to a set of principles and practices that leverage the language's unique design. |
| 4 | +Here are some key guidelines, often considered "commandments" in the Go community: |
| 5 | + |
| 6 | +**The Ten Commandments of Idiomatic Go:** |
| 7 | + |
| 8 | +1. **Thou Shalt Format Thy Code with `golangci-lint`:** |
| 9 | + |
| 10 | + * **Guideline:** Use the `golangci-lint` tool religiously. It enforces a standard, opinionated style for indentation, spacing, and alignment. |
| 11 | + We support the tool directly in our `Makefile`. You can run: |
| 12 | + ```bash |
| 13 | + make lint |
| 14 | + ``` |
| 15 | + and |
| 16 | + ```bash |
| 17 | + make checks |
| 18 | + ``` |
| 19 | + * This consistency makes Go code highly readable and reduces time spent on style debates. Many editors and IDEs integrate `gofmt` automatically on save. The `goimports` tool is a superset of `gofmt` that also manages imports. |
| 20 | + * **References:** |
| 21 | + * [Effective Go - Formatting](https://www.google.com/search?q=https://go.dev/doc/effective_go%23formatting) |
| 22 | + * [Go standards and style guidelines - GitLab Docs](https://docs.gitlab.com/development/go_guide/) (Mentions `goimports`) |
| 23 | + * [golangci-lint Fast linters runner for Go](https://github.com/golangci/golangci-lint) |
| 24 | + |
| 25 | +2. **Thou Shalt Handle Errors Explicitly:** |
| 26 | + |
| 27 | + * **Guideline:** Go treats errors as values. Functions that can fail should return an error as the last return value. |
| 28 | + Always check error returns and handle them gracefully. Avoid ignoring errors using the blank identifier `_`. |
| 29 | + Propagate errors back up the call stack or handle them appropriately (e.g., logging, retrying). |
| 30 | + Use `errors.Is` and `errors.As` for checking error types or values, especially in Go 1.13+. Error strings should be lowercase and not end with punctuation. |
| 31 | + * **References:** |
| 32 | + * [Effective Go - Errors](https://www.google.com/search?q=https://go.dev/doc/effective_go%23errors) |
| 33 | + * [Golang 10 Best Practices - Proper Error Handling](https://codefinity.com/blog/Golang-10-Best-Practices) |
| 34 | + * [Go standards and style guidelines - GitLab Docs](https://docs.gitlab.com/development/go_guide/) (Mentions `errors.Is` and `errors.As`) |
| 35 | + |
| 36 | +3. **Thou Shalt Favor Composition Over Inheritance:** |
| 37 | + |
| 38 | + * **Guideline:** Go does not have traditional class inheritance. |
| 39 | + Achieve code reuse and flexibility through composition (embedding structs) and interfaces. |
| 40 | + Design small, focused interfaces that define behavior. |
| 41 | + * **References:** |
| 42 | + * [Idiomatic Design Patterns in Go - Composition](https://ayada.dev/go-roadmap/idiomatic-design-patterns-in-go/) |
| 43 | + |
| 44 | +4. **Thou Shalt Design Small, Focused Interfaces:** |
| 45 | + |
| 46 | + * **Guideline:** Go's interfaces are implicitly implemented. |
| 47 | + Define interfaces on the consumer side, specifying only the methods a client needs. |
| 48 | + This promotes decoupling and testability. |
| 49 | + Name interfaces with an "-er" suffix (e.g., `Reader`, `Writer`) when they define a single method, though this is a convention, not a strict rule for all interfaces. |
| 50 | + * **References:** |
| 51 | + * [Effective Go - Interfaces](https://www.google.com/search?q=https://go.dev/doc/effective_go%23interfaces) |
| 52 | + * [Golang style guide - Mattermost Developers](https://www.google.com/search?q=https://developers.mattermattermost.com/contribute/more-info/server/style-guide/%23interfaces) (Mentions the "-er" convention) |
| 53 | +
|
| 54 | +5. **Thou Shalt Write Concurrent Code Using Goroutines and Channels:** |
| 55 | +
|
| 56 | + * **Guideline:** Embrace Go's built-in concurrency primitives. |
| 57 | + Use goroutines for concurrent execution and channels for safe communication and synchronization between them. |
| 58 | + Understand the Go memory model and use tools like the race detector to avoid race conditions. |
| 59 | + * **References:** |
| 60 | + * [Effective Go - Concurrency](https://www.google.com/search?q=https://go.dev/doc/effective_go%23concurrency) |
| 61 | + * [Golang 10 Best Practices - Efficient Use of Goroutines](https://codefinity.com/blog/Golang-10-Best-Practices) |
| 62 | + * [Idiomatic Design Patterns in Go - Concurrency with Goroutines and Channels](https://ayada.dev/go-roadmap/idiomatic-design-patterns-in-go/) |
| 63 | + |
| 64 | +6. **Thou Shalt Not Use Global Variables Extensively:** |
| 65 | + |
| 66 | + * **Guideline:** Limit the use of global variables to avoid side effects and improve testability and maintainability. |
| 67 | + Pass data explicitly through function parameters and return values, or use struct fields. |
| 68 | + * **References:** |
| 69 | + * [Golang 10 Best Practices - Minimize Global Variables](https://codefinity.com/blog/Golang-10-Best-Practices) |
| 70 | + * [Go standards and style guidelines - GitLab Docs](https://docs.gitlab.com/development/go_guide/) (Avoid global variables) |
| 71 | + |
| 72 | +7. **Thou Shalt Keep Functions Small and Single-Purpose:** |
| 73 | + |
| 74 | + * **Guideline:** Design functions that do one thing well. |
| 75 | + Short, focused functions are easier to understand, test, and maintain. |
| 76 | + Avoid excessive nesting and complex logic within a single function. |
| 77 | + * **References:** |
| 78 | + * [Golang 10 Best Practices - Keep Functions Focused](https://codefinity.com/blog/Golang-10-Best-Practices) |
| 79 | + * [Golang Clean Code Guide – 2 - Simplicity in Action: Short and Focused Functions](https://withcodeexample.com/golang-clean-code-guide-2/) |
| 80 | + |
| 81 | +8. **Thou Shalt Write Tests:** |
| 82 | + |
| 83 | + * **Guideline:** Go has a built-in testing framework. |
| 84 | + Write unit tests for your code to ensure correctness and provide examples of how to use your functions and types. |
| 85 | + Table-driven tests are a common and effective pattern in Go. |
| 86 | + * **References:** |
| 87 | + * [Effective Go - Testing](https://www.google.com/search?q=https://go.dev/doc/effective_go%23testing) |
| 88 | + * [Go standards and style guidelines - GitLab Docs](https://docs.gitlab.com/development/go_guide/) (Defining test cases) |
| 89 | + |
| 90 | +9. **Thou Shalt Document Exported Symbols:** |
| 91 | + |
| 92 | + * **Guideline:** Provide clear and concise documentation for all exported functions, types, variables, and constants. |
| 93 | + Comments should explain *what* the code does and *why*, especially for non-obvious parts. |
| 94 | + Use Godoc conventions for easily generated documentation. |
| 95 | + * **References:** |
| 96 | + * [Go Doc Comments - The Go Programming Language](https://go.dev/doc/comment) |
| 97 | + * [Documentation and Comments in Go - With Code Example](https://withcodeexample.com/golang-documentation-and-comments-guide) |
| 98 | + |
| 99 | +10. **Thou Shalt Be Mindful of Performance and Allocations:** |
| 100 | + |
| 101 | + * **Guideline:** While Go is performant, be aware of potential bottlenecks. |
| 102 | + Understand how slices, maps, and pointers work to minimize unnecessary allocations and garbage collection pressure, especially in performance-critical code. |
| 103 | + Use tools like the pprof profiler to identify performance issues. |
| 104 | + |
| 105 | +**Additional Recommended Reading and Style Guides:** |
| 106 | + |
| 107 | +* [Effective Go](https://go.dev/doc/effective_go) - A fundamental guide from the Go team on writing clear, idiomatic Go code. |
| 108 | +* [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments) - A wiki page listing common style issues and suggestions. |
| 109 | +* [Google Go Style Guide](https://google.github.io/styleguide/go/) - Google's internal style guide for Go. |
| 110 | +* [Uber Go Style Guide](https://github.com/uber-go/guide) - Uber's widely referenced style guide for Go. |
| 111 | + |
| 112 | +These resources provide more detailed explanations and examples for each of the guidelines mentioned above, helping you to write more effective and idiomatic Go code. |
0 commit comments