mit einem Klick
golang
Golang Development Guidelines
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Menü
Golang Development Guidelines
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Basierend auf der SOC-Berufsklassifikation
| name | golang |
| description | Golang Development Guidelines |
You are an expert Go developer who follows Test-Driven Development (TDD) principles, hexagonal architecture, and Go best practices.
Build, lint, architecture check, and test MUST ALWAYS be passing.
Before completing any task, verify:
task build succeeds with no errorstask test passes all teststask lint reports no issuesgo-arch-lint check passes (if .go-arch-lint.yml exists)NEVER leave code in a broken state. Always use Taskfile targets. If no Taskfile exists, STOP and report an error.
DO NOT MODIFY linting configuration files (.golangci.yml, .go-arch-lint.yml, .go-ai-lint.yml, Taskfile.yml). These are project-level standards. Fix the code, not the rules.
NEVER disable linting - Do not use //nolint: directives. Do not remove, comment out, or disable lint rules. If lint fails, fix the underlying code issue.
All Go projects MUST follow Hexagonal/Onion Architecture:
go-arch-lint to enforce architectural boundariesAll service CLI entry points MUST use Cobra and Viper:
cmd/<app>/root.go, subcommands in separate filesviper.BindPFlag("key", cmd.Flags().Lookup("flag"))All tests MUST use testify for assertions and mocking:
assert for non-fatal assertions, require for fatal assertionsmock package for mock generation and verificationsuite package for test suites when appropriateimport (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestExample(t *testing.T) {
require.NotNil(t, result, "result should not be nil")
assert.Equal(t, expected, actual, "values should match")
assert.NoError(t, err, "operation should succeed")
}
ALWAYS follow the TDD cycle:
Testing Best Practices:
t.Run() for better test organizationproject/
├── cmd/ # COMPOSITION ROOT: Wires all dependencies
│ └── myapp/
│ └── main.go # Dependency injection, bootstrap
├── internal/
│ ├── domain/ # INNER LAYER: Pure business logic
│ │ ├── user.go # Entities, value objects
│ │ └── errors.go # Domain errors
│ ├── ports/ # INNER LAYER: Interfaces (contracts)
│ │ ├── repositories.go
│ │ └── services.go
│ ├── application/ # APPLICATION LAYER: Use cases
│ │ └── user_service.go # Orchestrates domain logic
│ ├── adapters/ # OUTER LAYER: Infrastructure
│ │ ├── handlers/ # HTTP/gRPC handlers (primary/driving)
│ │ │ ├── http/
│ │ │ └── grpc/
│ │ └── repositories/ # Database implementations (secondary/driven)
│ │ ├── postgres/
│ │ └── redis/
│ └── config/ # Configuration loading
├── pkg/ # PUBLIC PACKAGES: Reusable library code
├── .go-arch-lint.yml # Architecture enforcement rules
├── .golangci.yml # Linting rules
└── go.mod
adapters -> ports (adapters implement port interfaces)
application -> ports (application uses port interfaces)
domain -> (nothing) (domain is pure, no dependencies)
ports -> domain (ports reference domain types)
pkg -> (vendor) (pkg only uses external libraries)
cmd -> (all) (cmd wires everything together)
Package Design Principles:
internal/ for code that shouldn't be imported by external projectspkg/ for code that could be reused in other projectsReader, Writer, UploaderUserRepository not UserRepositoryInterfaceUserRepository not IUserRepositoryKeep function names simple and rely on package context:
uploader.Upload() - package name provides contextuploader.UploaderUpload() - redundantPackage names are part of the description:
http, use Client not HTTPClientstorage, use Save not StorageSaveparser, use Parse not ParseJSONDo NOT document edge cases or implementation details in function names:
Upload() - implementation details are hiddenUploadWithRetries(), UploadWithBackoff()Best practices (retries, backoffs, jitter, timeouts) are implicit. Use options or configuration to control behavior.
Prefer wrapper functions with parameters over new function names:
GOOD: Add a parameter to control behavior
func Process(data []byte, opts ...Option) error
BAD: Create a new function for each variant
func Process(data []byte) error
func ProcessWithValidation(data []byte) error
func ProcessWithValidationAndRetries(data []byte) error
Owner() not GetOwner()func Read() ([]byte, error)fmt.Errorf("failed to read file: %w", err)// Guard clause pattern (GOOD)
func Process(data []byte) error {
if len(data) == 0 {
return errors.New("empty data")
}
result, err := transform(data)
if err != nil {
return fmt.Errorf("transform failed: %w", err)
}
return save(result)
}
select to multiplex channel operationssync.WaitGroup to wait for goroutines to completecontext.Context for cancellation and timeoutstask build (must pass)task test (must pass)task lint (must pass)go-arch-lint check (must pass, if config exists)type Option func(*Config)
func WithRetries(n int) Option {
return func(c *Config) {
c.Retries = n
}
}
func Upload(data []byte, opts ...Option) error {
cfg := DefaultConfig
for _, opt := range opts {
opt(&cfg)
}
// Use cfg
}
func TestProcess(t *testing.T) {
tests := []struct {
name string
input []byte
want Result
wantErr bool
}{
{"empty input", []byte{}, Result{}, true},
{"valid input", []byte("data"), Result{Value: "data"}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Process(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
type Uploader interface {
Upload(ctx context.Context, data []byte) error
}
type MockUploader struct {
UploadFunc func(ctx context.Context, data []byte) error
}
func (m *MockUploader) Upload(ctx context.Context, data []byte) error {
if m.UploadFunc != nil {
return m.UploadFunc(ctx, data)
}
return nil
}
# Install golangci-lint
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
# Install go-arch-lint
go install github.com/fe3dback/go-arch-lint@latest
# Full validation (run before every commit)
task build
task test
task lint
go-arch-lint check
# Quick architecture visualization
go-arch-lint graph
When you encounter a linting error:
Common Lint Errors and Correct Fixes:
| Error | WRONG Fix | CORRECT Fix |
|---|---|---|
defer in loop | Remove defer | Extract to helper function |
error ignored | Add _ = err | Handle the error or wrap and return |
nil map write | Remove the write | Initialize with make(map[K]V) |
context.TODO() | Use context.Background() | Accept context.Context as first parameter |
GetX() naming | Rename to GetterX() | Rename to X() (drop Get prefix) |
Interface suffix | Rename to IRepository | Rename to Repository (drop suffix/prefix) |
Ports (interfaces) define contracts. Any implementation must handle edge cases identically. Contract tests enforce this.
// internal/ports/card_repository_contract.go
// RunCardRepositoryContract tests any CardRepository implementation.
// All implementations (postgres, mock, in-memory) MUST pass these tests.
func RunCardRepositoryContract(t *testing.T, repo CardRepository, cleanup func()) {
t.Helper()
t.Run("Create_NilTags", func(t *testing.T) {
if cleanup != nil {
t.Cleanup(cleanup)
}
card := &domain.Card{
ID: uuid.New(),
Tags: nil, // Edge case: nil not empty slice
Front: "test",
Back: "test",
}
err := repo.Create(context.Background(), card)
require.NoError(t, err, "nil tags must be handled")
})
t.Run("Create_NilCard", func(t *testing.T) {
err := repo.Create(context.Background(), nil)
require.ErrorIs(t, err, domain.ErrInvalidInput)
})
}
Required Edge Cases for All Repository Contracts:
| Input | Required Behavior |
|---|---|
nil slice fields | Treat as empty, never panic |
nil entity pointer | Return ErrInvalidInput |
| Zero/nil UUID | Return ErrInvalidInput |
| Entity not found | Return typed error (ErrCardNotFound) |
| Duplicate key | Return typed error (ErrDuplicateKey) |
| Context cancelled | Return ctx.Err() or wrapped error |
| Task | Command |
|---|---|
| Build | task build |
| Test | task test |
| Lint | task lint |
| Architecture check | go-arch-lint check |
| Architecture graph | go-arch-lint graph |
Write tests first with testify, follow hexagonal architecture, keep domain pure, use interfaces for dependencies, use contract tests for ports, use Cobra/Viper for CLI entry points, ensure build/lint/arch-check/test always pass, and never use emojis.
Bash Shell Script Development Guidelines
Go Project Planning Skill
Godot C# Game Development Skill
Godot Game Development Skill
Grill Me - Relentless Design Interview
Helios Design System (Generic)