AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Golang Development

skill-brpaz-agent-skills-golang-development · by brpaz

Write and review Go code with idiomatic project structure, errors, concurrency, testing, and performance guidance.

No reviews yet
0 installs
38 views
0.0% view→install

Install

$ agentstack add skill-brpaz-agent-skills-golang-development

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access Used
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-brpaz-agent-skills-golang-development)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Golang Development? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Go (Golang) - Patterns and Guidance

Use this skill when writing, reviewing, or debugging Go code. Covers idiomatic Go patterns, project structure, concurrency, testing, and production-ready practices.

When to Use

  • Writing new Go packages, services, or CLI tools
  • Reviewing or refactoring existing Go code for idiomatic style
  • Debugging Go concurrency, error handling, or performance issues
  • Setting up Go project structure, module layout, or test harness

Go Philosophy

Core principles:

  • Simplicity over cleverness
  • Explicit over implicit
  • Composition over inheritance
  • Clear is better than clever
  • Errors are values
  • Concurrency is not parallelism

Key idioms:

  • "Don't communicate by sharing memory; share memory by communicating"
  • "A little copying is better than a little dependency"
  • "The bigger the interface, the weaker the abstraction"
  • "Make the zero value useful"
  • "Accept interfaces, return structs"

Project Structure

Standard Layout

myproject/
├── cmd/                    # Main applications
│   ├── api/
│   │   └── main.go        # API server entry point
│   └── worker/
│       └── main.go        # Background worker entry point
├── internal/              # Private application code
│   ├── app/              # Application logic
│   ├── domain/           # Domain models
│   └── platform/         # Platform-specific code
├── pkg/                   # Public libraries (reusable)
│   ├── auth/
│   └── logger/
├── api/                   # API definitions (OpenAPI, protobuf)
├── web/                   # Web assets (templates, static files)
├── scripts/               # Build, install, analysis scripts
├── configs/               # Configuration files
├── deployments/           # Deployment configs (docker, k8s)
├── test/                  # Additional test data
├── docs/                  # Documentation
├── examples/              # Example code
├── tools/                 # Supporting tools
├── vendor/                # Vendored dependencies (optional)
├── go.mod                 # Module definition
├── go.sum                 # Dependency checksums
├── Makefile              # Build automation
└── README.md

Key directories:

| Directory | Purpose | Public/Private | |-----------|---------|----------------| | cmd/ | Main applications (one per binary) | Private | | internal/ | Private application code (cannot be imported) | Private | | pkg/ | Public libraries (can be imported by others) | Public | | api/ | API definitions, schemas | Public |

Rules:

  • internal/ cannot be imported by external packages (enforced by Go compiler)
  • One main.go per cmd// subdirectory
  • Keep pkg/ minimal. Place application code in internal/ unless other modules must import it.
  • Flat is better than nested - avoid deep hierarchies

Minimal Project

For small projects:

myproject/
├── main.go
├── handler.go
├── service.go
├── repository.go
├── go.mod
├── go.sum
└── README.md

Package Naming

// ❌ BAD: Stuttering
auth.AuthService
user.UserRepository
http.HTTPClient

// ✅ GOOD: Concise
auth.Service
user.Repository
http.Client

Rules:

  • Lowercase, single word
  • No underscores or mixedCaps
  • Avoid generic names (util, common, base, helper)
  • Name by purpose, not type (auth, logger, not structs, interfaces)

Error Handling

Basic Pattern

// ✅ GOOD: Immediate error check
result, err := doSomething()
if err != nil {
    return nil, err
}

// ❌ BAD: Deferred error check
result, err := doSomething()
// ... many lines ...
if err != nil {
    return nil, err
}

Error Wrapping

// ✅ GOOD: Wrap errors with context
func processUser(id int) error {
    user, err := fetchUser(id)
    if err != nil {
        return fmt.Errorf("failed to fetch user %d: %w", id, err)
    }
    
    if err := saveUser(user); err != nil {
        return fmt.Errorf("failed to save user %d: %w", id, err)
    }
    
    return nil
}

// Check wrapped errors
err := processUser(123)
if errors.Is(err, sql.ErrNoRows) {
    // Handle specific error
}

Use %w for wrapping, %v for opaque errors.

Custom Errors

// Define sentinel errors for expected conditions
var (
    ErrUserNotFound = errors.New("user not found")
    ErrInvalidInput = errors.New("invalid input")
    ErrUnauthorized = errors.New("unauthorized")
)

// Use in code
func getUser(id int) (*User, error) {
    if id  0 {
            result = append(result, item)
        }
    }
    return result
}

// ✅ GOOD: Reuse slice
func process(items []int, result []int) []int {
    result = result[:0] // Reset length
    for _, item := range items {
        if item > 0 {
            result = append(result, item)
        }
    }
    return result
}

Sync.Pool for Temporary Objects

var bufferPool = sync.Pool{
    New: func() interface{} {
        return new(bytes.Buffer)
    },
}

func processData(data []byte) {
    buf := bufferPool.Get().(*bytes.Buffer)
    defer func() {
        buf.Reset()
        bufferPool.Put(buf)
    }()
    
    buf.Write(data)
    // Use buf
}

Profiling

import _ "net/http/pprof"

func main() {
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()
    
    // Your application code
}

Access profiles:

  • CPU: http://localhost:6060/debug/pprof/profile
  • Heap: http://localhost:6060/debug/pprof/heap
  • Goroutines: http://localhost:6060/debug/pprof/goroutine

Analyze:

go tool pprof http://localhost:6060/debug/pprof/profile

Common Pitfalls

Range Loop Variable Capture

// ❌ BAD: Captures loop variable
for _, item := range items {
    go func() {
        fmt.Println(item) // All goroutines print last item
    }()
}

// ✅ GOOD: Capture explicitly
for _, item := range items {
    item := item // Reassign
    go func() {
        fmt.Println(item)
    }()
}

// ✅ GOOD: Pass as parameter
for _, item := range items {
    go func(i Item) {
        fmt.Println(i)
    }(item)
}

Nil Interface Gotcha

// ❌ BAD: Interface is not nil
func returnsError() error {
    var p *MyError = nil
    return p // error interface is not nil!
}

err := returnsError()
if err != nil {
    // This block executes!
}

// ✅ GOOD: Return explicit nil
func returnsError() error {
    var p *MyError = nil
    if p == nil {
        return nil
    }
    return p
}

Defer in Loops

// ❌ BAD: Defer accumulates
for _, file := range files {
    f, err := os.Open(file)
    if err != nil {
        return err
    }
    defer f.Close() // Won't run until function returns
}

// ✅ GOOD: Close immediately or use function
for _, file := range files {
    if err := processFile(file); err != nil {
        return err
    }
}

func processFile(filename string) error {
    f, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer f.Close()
    
    // Process file
    return nil
}

Slice Append Gotcha

// ❌ BAD: Original slice affected
a := []int{1, 2, 3}
b := a[:2]
b = append(b, 4)
// a is now [1, 2, 4]

// ✅ GOOD: Copy slice
a := []int{1, 2, 3}
b := make([]int, len(a[:2]))
copy(b, a[:2])
b = append(b, 4)
// a is still [1, 2, 3]

Map Concurrent Access

// ❌ BAD: Concurrent map writes cause panic
m := make(map[string]int)

go func() {
    m["key"] = 1
}()

go func() {
    m["key"] = 2
}()

// ✅ GOOD: Use sync.Map or mutex
var mu sync.Mutex
m := make(map[string]int)

go func() {
    mu.Lock()
    m["key"] = 1
    mu.Unlock()
}()

go func() {
    mu.Lock()
    m["key"] = 2
    mu.Unlock()
}()

Production Guidance

Logging

// Use structured logging
import "go.uber.org/zap"

logger, _ := zap.NewProduction()
defer logger.Sync()

logger.Info("user logged in",
    zap.Int("user_id", 123),
    zap.String("ip", "192.168.1.1"),
)

logger.Error("failed to process request",
    zap.Error(err),
    zap.String("request_id", reqID),
)

Configuration

// Use environment variables or config files
import "github.com/spf13/viper"

func loadConfig() (*Config, error) {
    viper.SetConfigName("config")
    viper.SetConfigType("yaml")
    viper.AddConfigPath(".")
    viper.AddConfigPath("/etc/myapp/")
    
    viper.SetEnvPrefix("MYAPP")
    viper.AutomaticEnv()
    
    if err := viper.ReadInConfig(); err != nil {
        return nil, err
    }
    
    var cfg Config
    if err := viper.Unmarshal(&cfg); err != nil {
        return nil, err
    }
    
    return &cfg, nil
}

Graceful Shutdown

func main() {
    srv := &http.Server{
        Addr:    ":8080",
        Handler: handler,
    }
    
    go func() {
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("listen: %s\n", err)
        }
    }()
    
    // Wait for interrupt signal
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit
    
    log.Println("Shutting down server...")
    
    // Graceful shutdown with timeout
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server forced to shutdown:", err)
    }
    
    log.Println("Server exiting")
}

Database Connections

import "database/sql"

func initDB() (*sql.DB, error) {
    db, err := sql.Open("postgres", connStr)
    if err != nil {
        return nil, err
    }
    
    // Connection pool settings
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(5)
    db.SetConnMaxLifetime(5 * time.Minute)
    
    // Verify connection
    if err := db.Ping(); err != nil {
        return nil, err
    }
    
    return db, nil
}

Context Propagation

// Always pass context as first parameter
func fetchUser(ctx context.Context, userID int) (*User, error) {
    // Use context for cancellation, timeouts, and values
    if err := ctx.Err(); err != nil {
        return nil, err
    }
    
    // Pass context to downstream calls
    return db.GetUser(ctx, userID)
}

// HTTP handler
func handler(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    
    user, err := fetchUser(ctx, 123)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    json.NewEncoder(w).Encode(user)
}

Tools and Commands

Essential Commands

# Format code
go fmt ./...

# Lint code (requires golangci-lint)
golangci-lint run

# Run tests
go test ./...

# Run tests with coverage
go test -cover ./...

# Run tests with race detector
go test -race ./...

# Run benchmarks
go test -bench=. ./...

# Build binary
go build -o myapp ./cmd/myapp

# Install dependencies
go mod download

# Tidy dependencies
go mod tidy

# Vendor dependencies
go mod vendor

# Update dependencies
go get -u ./...

# View documentation
go doc fmt.Println

# Run code
go run main.go

Useful Tools

| Tool | Purpose | Install | |------|---------|---------| | golangci-lint | Comprehensive linter | go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest | | gofmt | Code formatter | Built-in | | goimports | Import formatter | go install golang.org/x/tools/cmd/goimports@latest | | staticcheck | Static analysis | go install honnef.co/go/tools/cmd/staticcheck@latest | | govulncheck | Vulnerability scanner | go install golang.org/x/vuln/cmd/govulncheck@latest | | dlv | Debugger | go install github.com/go-delve/delve/cmd/dlv@latest |

Makefile Example

.PHONY: build test lint clean

build:
	go build -o bin/myapp ./cmd/myapp

test:
	go test -v -race -cover ./...

lint:
	golangci-lint run

clean:
	rm -rf bin/

install-tools:
	go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
	go install golang.org/x/tools/cmd/goimports@latest

run:
	go run ./cmd/myapp

Rules

  • ALWAYS check errors immediately - defer error checks only when a later check is intentional and documented.
  • ALWAYS use context.Context as the first parameter of functions that do I/O or long-running work.
  • ALWAYS close resources with defer immediately after opening them (files, connections, etc.).
  • ALWAYS use go fmt before committing code - no exceptions.
  • ALWAYS run tests with -race flag to catch race conditions.
  • NEVER ignore errors - at minimum, log them; never use _ for error returns.
  • NEVER use panic for expected errors - panic only for truly unrecoverable situations (programmer errors).
  • NEVER share memory by communicating - communicate by sharing memory (use channels over mutexes when possible).
  • NEVER mutate slices/maps without understanding capacity - be aware of shared underlying arrays.
  • Accept interfaces, return structs - keep APIs flexible by accepting interfaces but returning concrete types.
  • Define interfaces where they're used, not where they're implemented (consumer-side).
  • Keep interfaces small - single-method interfaces are ideal.
  • Use table-driven tests for comprehensive test coverage with minimal code.
  • Preallocate slices when size is known - use make([]T, 0, capacity).
  • Use strings.Builder for string concatenation in loops - never concatenate strings with +.
  • Pass context to downstream functions - never create new context in the middle of a call chain.
  • Name packages by purpose, not type - auth, not structs; logger, not interfaces.
  • Avoid stuttering in names - user.Repository, not user.UserRepository.

Quick Reference

Minimal HTTP Server

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func main() {
    http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
        users := []User{
            {ID: 1, Name: "Alice"},
            {ID: 2, Name: "Bob"},
        }
        
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(users)
    })
    
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Minimal CLI App

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    name := flag.String("name", "World", "name to greet")
    flag.Parse()
    
    fmt.Printf("Hello, %s!\n", *name)
}

Module Initialization

# Initialize module
go mod init github.com/myorg/myapp

# Add dependency
go get github.com/pkg/errors

# Remove unused dependencies
go mod tidy

Resources

Inputs

  • Go source files, module (go.mod), and description of the feature, bug, or refactoring goal
  • Target Go version and any relevant package constraints

Outputs

  • Idiomatic Go code following standard project layout, explicit error handling, and table-driven tests

Examples

// Idiomatic error wrapping
func getUser(id int) (*User, error) {
    u, err := db.QueryUser(id)
    if err != nil {
        return nil, fmt.Errorf("getUser %d: %w", id, err)
    }
    return u, nil
}

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.