Channels vs mutexes
Channels for coordination: passing data around. Mutexes for state: struct fields, cache maps, counters.
Write Go like a pro
Channels for coordination: passing data around. Mutexes for state: struct fields, cache maps, counters.
Producer closes the channel, consumer cancels the context.
Avoid running a producer and consumer on the same goroutine. Always have a clear exit path.
Use context.Context.
Start your feature with one file. Add more files only when you actually need them.
Keep it simple and small.
Organize your code by features, not by technical layers.
This probably matters more in Go than in other languages, because in Go a package is the directory, the namespace and the visibility boundary at the same time.
Prefer standard library over third-party packages, whenever possible and practical. Every external dependency you add is one more thing you have to maintain.
Ideally, an error should be either handled (logged) or returned to the caller.
This is to avoid logging the same error three times in three different layers, so your dashboard does not count it three times - which looks confusing and misleading. It keeps your error stack trace clean and readable.
Accept interfaces, return structs. This is by far the hardest one for new Go developers.
Structs are not classes. I am sorry to break it to you.
If you treat them like classes, they will become unmanageable god objects - and you will fight the system (your codebase) the whole time.
In Go, a name is good if it reads well.