1. The Functional Options Pattern

Instead of passing a large config struct or multiple parameters, use functional options to make your API clean and extensible.

type Server struct {
    host string
    port int
    timeout time.Duration
}

type Option func(*Server)

func WithTimeout(d time.Duration) Option {
    return func(s *Server) { s.timeout = d }
}

func NewServer(host string, port int, opts ...Option) *Server {
    s := &Server{host: host, port: port, timeout: 30 * time.Second}
    for _, opt := range opts { opt(s) }
    return s
}

2. Slice Filtering without Allocation

You can filter a slice in place without allocating a new underlying array.

func Filter(s []int, keep func(int) bool) []int {
    n := 0
    for _, x := range s {
        if keep(x) {
            s[n] = x
            n++
        }
    }
    return s[:n]
}

3. WaitGroup Wrapper for Goroutines

A cleaner way to handle goroutines using a WaitGroup to prevent panic from leaving the WaitGroup unbalanced.

func RunSafe(wg *sync.WaitGroup, fn func()) {
    wg.Add(1)
    go func() {
        defer wg.Done()
        defer func() {
            if err := recover(); err != nil {
                log.Printf("Recovered from panic: %v", err)
            }
        }()
        fn()
    }()
}

4. Using Empty Structs for Sets

Since Go doesn't have a built-in Set type, you can use a map with empty structs to save memory, as `struct{}` takes 0 bytes.

type Set map[string]struct{}

func main() {
    mySet := make(Set)
    mySet["apple"] = struct{}{}
    
    if _, exists := mySet["apple"]; exists {
        fmt.Println("Apple is in the set!")
    }
}