🧰 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 testing package and keep tests in *_test.go files.

  • βš™οΈ Use go fmt, go vet, and golangci-lint.

1. 🧠 Code Design

  • βœ… Keep functions small and focused β€” one responsibility per function.

  • πŸ§ͺ Prefer pure functions when possible (no side effects).

  • 🧱 Use struct to 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., Log struct in search results).

3. 🧱 Structs as β€œClasses”

  • Use struct for 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.