π§° Pro Tips for Writing Idiomatic Go
General Best Practices
-
π§ Follow Go naming conventions:
-
Exported names start with capital letters.
-
Keep names short and descriptive.
-
-
π Organize code by domain/package, not layers.
-
π§ͺ Always test! Use
testingpackage and keep tests in*_test.gofiles. -
βοΈ Use
go fmt,go vet, andgolangci-lint.
1. π§ Code Design
-
β Keep functions small and focused β one responsibility per function.
-
π§ͺ Prefer pure functions when possible (no side effects).
-
π§± Use
structto represent entities with state. -
βοΈ Use methods with receivers when behavior depends on internal state.
-
π§© Use interfaces to decouple components and make testing easier.
- Define interfaces where they are used, not globally.
-
π Favor composition over inheritance.
-
πͺΆ Avoid unnecessary abstraction β Go values clarity over flexibility.
2. π¦ Data and Pointers
-
π Use pointers (
*Type) when:-
You need to modify the original value.
-
You want to avoid copying large structs.
-
-
π Use values (
Type) when:-
The data is small and immutable.
-
You want clear ownership (e.g.,
Logstruct in search results).
-
3. π§± Structs as βClassesβ
-
Use
structfor data + methods with receiver when behavior belongs to the entity. -
Example:
type LogService struct { esClient ElasticSearchClient } func (s *LogService) Process(log Log) error { // logic using internal state }
4. π§© Interfaces
-
β Keep them small (1-2 methods).
-
π Define them at the consumer side, not producer.
-
Example:
type ElasticSearchClient interface { Index(ctx context.Context, index string, id string, body interface{}) error }
5. π§ Error Handling
-
Return
(result, error)and handle errors immediately. -
Prefer clarity over cleverness:
res, err := doSomething()
if err != nil {
return nil, err
}
6. π Concurrency
-
π§΅ Use goroutines (
go func() { ... }()) for async tasks. -
π‘ Use channels for safe communication between goroutines.
-
π Protect shared state with sync.Mutex or channel patterns.