Blog cikk

Top 10 Go Tricks to Make Your Development Easier

Go (Golang) is famous for its simplicity, speed, and reliability.

readytools

July 1, 2026

3 perc olvasás

Top 10 Go Tricks to Make Your Development Easier

Image source: encrypted-tbn0.gstatic.com

Megosztás

Go (Golang) is famous for its simplicity, speed, and reliability. But even with its clean syntax, there are plenty of practical tricks that can save you time, reduce bugs, and make your code more idiomatic. Here are 10 of the most useful Go tricks that seasoned developers use to write cleaner, faster, and more maintainable code

1. Use go run . and Build Tags for Quick Iteration

Forget typing long go run main.go commands. Just run:

BASH
go run .

For even more power, use build tags to toggle features during development:

GO
// +build debug
package main

Or with the modern syntax:

GO
//go:build debug

This lets you keep debug code without polluting production builds.

2. Embed Static Files with embed

Since Go 1.16, embedding files is built-in and incredibly useful for CLIs, web servers, or templates:

GO
import "embed"
//go:embed templates/*
var templates embed.FS
//go:embed static/*
var static embed.FS

No more external dependencies or complex asset pipelines. Perfect for single-binary deployments.

3. Functional Options Pattern for Flexible Constructors

Instead of massive config structs or many constructor variants, use the Functional Options pattern:

GO
type Server struct {
    addr string
    port int
    tls  bool
}
type Option func(*Server)
func WithTLS() Option { ... }
func NewServer(opts ...Option) *Server {
    s := &Server{addr: "localhost", port: 8080}
    for _, opt := range opts {
        opt(s)
    }
    return s
}

Clean, extensible, and very idiomatic.

4. context.Context Everywhere (and Proper Cancellation)

Always pass context.Context to functions that might be long-running or network-bound. Use context.WithTimeout or context.WithCancel liberally:

GO
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

This one habit prevents many goroutine leaks and makes your services more resilient.

5. Generics for Reducing Boilerplate (Go 1.18+)

Don’t fear generics. They shine for utilities like maps, sets, or data processing:

GO
func Map[T, U any](slice []T, fn func(T) U) []U {
    result := make([]U, len(slice))
    for i, v := range slice {
        result[i] = fn(v)
    }
    return result
}

Use them judiciously—don’t over-engineer, but they can eliminate a lot of copy-paste code.

6. sync.Once for Lazy Initialization

Need to initialize something exactly once across goroutines? sync.Once is perfect:

GO
var (
    once sync.Once
    db   *sql.DB
)
func getDB() *sql.DB {
    once.Do(func() {
        db = connectToDB()
    })
    return db
}

Simple, thread-safe, and cleaner than sync.Mutex + double-checked locking.

7. Error Wrapping with %w and errors.Is / errors.As

Always wrap errors for better debugging:

GO
return fmt.Errorf("failed to fetch user %d: %w", id, err)

Then check them properly:

GO
if errors.Is(err, sql.ErrNoRows) { ... }

This gives you rich error context without losing the original error type.

8. Use strings.Builder and bytes.Buffer Wisely

For performance-critical string building:

GO
var b strings.Builder
for _, item := range items {
    b.WriteString(item)
    b.WriteByte(',')
}
result := b.String()

Much more efficient than repeated += operations.

9. Table-Driven Tests and t.Run for Subtests

Level up your testing:

GO
func TestProcess(t *testing.T) {
    tests := []struct{
        name  string
        input string
        want  int
    }{ ... }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            // test logic
        })
    }
}

This keeps your tests organized and makes failures easy to pinpoint.

10. go:generate for Code Generation

Automate repetitive tasks with //go:generate:

GO
//go:generate stringer -type=Status
//go:generate mockgen -source=repository.go -destination=mock.go

Combine it with tools like wire, mockgen, or custom generators to keep your code DRY.


Bonus Tip: Get comfortable with go vet, staticcheck, and golangci-lint. Running a good linter locally (and in CI) catches many issues before they become problems. Go rewards simplicity and explicitness. These tricks help you stay in that sweet spot: expressive code that’s still fast and easy to reason about.


Építkezz gyorsabban a ReadyTools segítségével

Fedezd fel a ReadyTools-t: a tökéletes produktivitási csomagot alkotók számára. Gyönyörű Linksy oldalak, intelligens Lara AI, projektmenedzsment, biztonságos felhőtárhely és minden más, amire szükséged van — mind egy helyen. Kezdd el a 7 napos ingyenes próbaidőszakot még ma.

ReadyTools felfedezése

Tartalomjegyzék

1. Use go run . and Build Tags for Quick Iteration2. Embed Static Files with embed3. Functional Options Pattern for Flexible Constructors4. context.Context Everywhere (and Proper Cancellation)5. Generics for Reducing Boilerplate (Go 1.18+)6. sync.Once for Lazy Initialization7. Error Wrapping with %w and errors.Is / errors.As8. Use strings.Builder and bytes.Buffer Wisely9. Table-Driven Tests and t.Run for Subtests10. go:generate for Code Generation

Olvasd tovább

Kapcsolódó cikkek

Összes cikk megtekintése

Top eszközök

WorkspaceLinksyBoardlyChromoCodeHub

ReadyTools

KarrierKapcsolatEszközök
Árak7 nap ingyen
TámogatásÚtmutatókDocsBlogFrissítésekLaraVault

Nyelv kiválasztása

Téma beállítása

© 2026 ReadyTools. Minden jog fenntartva.