{
  "schemaVersion": "1.0",
  "item": {
    "slug": "afrexai-go-production",
    "name": "Go Production Engineering",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/1kalin/afrexai-go-production",
    "canonicalUrl": "https://clawhub.ai/1kalin/afrexai-go-production",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/afrexai-go-production",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-go-production",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/afrexai-go-production"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/afrexai-go-production",
    "agentPageUrl": "https://openagent3.xyz/skills/afrexai-go-production/agent",
    "manifestUrl": "https://openagent3.xyz/skills/afrexai-go-production/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/afrexai-go-production/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Go Production Engineering",
        "body": "You are a Go production engineering expert. Follow this system for every Go project — from architecture decisions through production deployment. Apply phases sequentially for new projects; use individual phases as needed for existing codebases."
      },
      {
        "title": "Quick Health Check (/16)",
        "body": "Score 0 (missing), 1 (partial), or 2 (solid) for each signal:\n\nSignalWhat to CheckProject structureStandard layout, clean package boundariesError handlingWrapped errors, sentinel errors, no swallowed errorsConcurrency safetyNo goroutine leaks, proper context propagationTesting>80% coverage, table-driven tests, race detector cleanObservabilityStructured logging, metrics, tracingConfiguration12-factor, validated at startupCI/CDLinting, testing, building in pipelineDocumentationGoDoc comments, README, ADRs\n\nScore interpretation: 0-6 = 🔴 Critical gaps | 7-10 = 🟡 Needs work | 11-14 = 🟢 Solid | 15-16 = 💎 Exemplary"
      },
      {
        "title": "Project Structure (Standard Layout)",
        "body": "project-root/\n├── cmd/\n│   ├── api/              # HTTP API binary\n│   │   └── main.go\n│   └── worker/           # Background worker binary\n│       └── main.go\n├── internal/             # Private packages (enforced by Go)\n│   ├── domain/           # Business types & interfaces\n│   │   ├── user.go\n│   │   └── order.go\n│   ├── service/          # Business logic\n│   │   ├── user.go\n│   │   └── user_test.go\n│   ├── repository/       # Data access\n│   │   ├── postgres/\n│   │   └── redis/\n│   ├── handler/          # HTTP/gRPC handlers\n│   │   ├── http/\n│   │   └── grpc/\n│   ├── middleware/        # HTTP middleware\n│   └── config/           # Configuration\n├── pkg/                  # Public packages (use sparingly)\n├── api/                  # OpenAPI specs, proto files\n├── migrations/           # Database migrations\n├── scripts/              # Build/deploy scripts\n├── Makefile\n├── Dockerfile\n├── go.mod\n├── go.sum\n└── .golangci.yml\n\n7 Architecture Rules:\n\ninternal/ is your best friend — use it aggressively to prevent leaky abstractions\ncmd/ contains only main.go files — wire dependencies here, zero business logic\nDomain types live in internal/domain/ — no external dependencies allowed in this package\nInterfaces are defined by the consumer, not the implementer (Go convention)\nOne package = one responsibility. If you can't name it in one word, split it\nAvoid pkg/ unless you genuinely intend the package to be imported by other projects\nCircular imports are compile errors in Go — design your dependency graph as a DAG"
      },
      {
        "title": "Dependency Injection Pattern",
        "body": "// cmd/api/main.go — wire everything here\nfunc main() {\n    cfg := config.MustLoad()\n    \n    // Infrastructure\n    db := postgres.MustConnect(cfg.Database)\n    cache := redis.MustConnect(cfg.Redis)\n    logger := logging.New(cfg.Log)\n    \n    // Repositories\n    userRepo := postgres.NewUserRepository(db)\n    orderRepo := postgres.NewOrderRepository(db)\n    \n    // Services\n    userSvc := service.NewUserService(userRepo, cache, logger)\n    orderSvc := service.NewOrderService(orderRepo, userSvc, logger)\n    \n    // Handlers\n    router := handler.NewRouter(userSvc, orderSvc, logger)\n    \n    // Server\n    srv := &http.Server{\n        Addr:         cfg.Server.Addr,\n        Handler:      router,\n        ReadTimeout:  cfg.Server.ReadTimeout,\n        WriteTimeout: cfg.Server.WriteTimeout,\n        IdleTimeout:  cfg.Server.IdleTimeout,\n    }\n    \n    // Graceful shutdown\n    go func() {\n        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {\n            logger.Fatal(\"server failed\", \"error\", err)\n        }\n    }()\n    \n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n    <-quit\n    \n    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n    defer cancel()\n    \n    if err := srv.Shutdown(ctx); err != nil {\n        logger.Fatal(\"forced shutdown\", \"error\", err)\n    }\n}"
      },
      {
        "title": "Framework & Library Selection",
        "body": "CategoryRecommendedAlternativeAvoidHTTP Routerchi, echogin, fibernet/http alone for APIsDatabasepgx (Postgres), sqlcGORM, entdatabase/sql directlyMigrationsgoose, golang-migrateatlasmanual SQL filesConfigviper, envconfigkoanfos.Getenv scatteredLoggingslog (stdlib), zerologzaplog (stdlib)Testingtestify, isgomock, mockerycustom assert helpersValidationvalidator/v10ozzo-validationmanual if-checksCLIcobraurfave/cliflag (stdlib) alonegRPCgoogle.golang.org/grpcconnect-go—ObservabilityOTel SDKprometheus clientcustom metrics\n\nSelection Rules:\n\nPrefer stdlib when it's good enough (slog, net/http for simple services, encoding/json)\npgx > database/sql for Postgres (performance, features, pgx pool)\nsqlc generates type-safe code from SQL — prefer over ORMs for query-heavy apps\nUse chi for REST APIs (stdlib-compatible, middleware ecosystem)\nFor gRPC, use connect-go if you want both gRPC and HTTP/JSON from one definition"
      },
      {
        "title": "Error Architecture",
        "body": "// internal/domain/errors.go — sentinel errors\npackage domain\n\nimport \"errors\"\n\nvar (\n    ErrNotFound      = errors.New(\"not found\")\n    ErrConflict      = errors.New(\"conflict\")\n    ErrUnauthorized  = errors.New(\"unauthorized\")\n    ErrForbidden     = errors.New(\"forbidden\")\n    ErrValidation    = errors.New(\"validation error\")\n    ErrInternal      = errors.New(\"internal error\")\n)\n\n// Typed error with context\ntype ValidationError struct {\n    Field   string\n    Message string\n}\n\nfunc (e *ValidationError) Error() string {\n    return fmt.Sprintf(\"validation: %s — %s\", e.Field, e.Message)\n}\n\nfunc (e *ValidationError) Unwrap() error {\n    return ErrValidation\n}"
      },
      {
        "title": "Error Wrapping Rules",
        "body": "// ✅ GOOD: Wrap with context using fmt.Errorf %w\nfunc (r *UserRepo) GetByID(ctx context.Context, id string) (*User, error) {\n    user, err := r.db.QueryRow(ctx, query, id)\n    if err != nil {\n        if errors.Is(err, pgx.ErrNoRows) {\n            return nil, fmt.Errorf(\"user %s: %w\", id, domain.ErrNotFound)\n        }\n        return nil, fmt.Errorf(\"get user %s: %w\", id, err)\n    }\n    return user, nil\n}\n\n// ❌ BAD: Swallowed error\nif err != nil {\n    log.Println(err) // logged but not returned — caller doesn't know it failed\n    return nil\n}\n\n// ❌ BAD: Bare return\nif err != nil {\n    return err // no context — impossible to debug in production\n}\n\n// ❌ BAD: String wrapping (breaks errors.Is/As)\nreturn fmt.Errorf(\"failed: %s\", err) // use %w, not %s or %v\n\n8 Error Handling Rules:\n\nAlways wrap errors with context: fmt.Errorf(\"doing X: %w\", err)\nUse %w verb — it preserves the error chain for errors.Is() and errors.As()\nDefine sentinel errors in the domain package for business-level errors\nHandle errors at the boundary (HTTP handler) — map to status codes there\nNever ignore errors: _ = f.Close() is a code smell. At minimum: defer func() { _ = f.Close() }()\nUse errors.Is() for sentinel comparisons, errors.As() for typed errors\nDon't log AND return an error — pick one (usually return; log at the top)\nPanics are for programmer errors only (impossible states) — never for runtime errors"
      },
      {
        "title": "HTTP Error Response Mapping",
        "body": "func mapError(err error) (int, string) {\n    switch {\n    case errors.Is(err, domain.ErrNotFound):\n        return http.StatusNotFound, \"resource not found\"\n    case errors.Is(err, domain.ErrConflict):\n        return http.StatusConflict, \"resource already exists\"\n    case errors.Is(err, domain.ErrUnauthorized):\n        return http.StatusUnauthorized, \"authentication required\"\n    case errors.Is(err, domain.ErrForbidden):\n        return http.StatusForbidden, \"insufficient permissions\"\n    case errors.Is(err, domain.ErrValidation):\n        var ve *domain.ValidationError\n        if errors.As(err, &ve) {\n            return http.StatusBadRequest, ve.Error()\n        }\n        return http.StatusBadRequest, \"invalid request\"\n    default:\n        return http.StatusInternalServerError, \"internal server error\"\n    }\n}"
      },
      {
        "title": "Context Propagation (Non-Negotiable)",
        "body": "// Every function that does I/O takes context as first parameter\nfunc (s *OrderService) Create(ctx context.Context, req CreateOrderRequest) (*Order, error) {\n    // Check cancellation before expensive operations\n    select {\n    case <-ctx.Done():\n        return nil, ctx.Err()\n    default:\n    }\n    \n    user, err := s.userRepo.GetByID(ctx, req.UserID)\n    if err != nil {\n        return nil, fmt.Errorf(\"get user: %w\", err)\n    }\n    \n    order, err := s.orderRepo.Create(ctx, user, req)\n    if err != nil {\n        return nil, fmt.Errorf(\"create order: %w\", err)\n    }\n    \n    // Fire-and-forget with NEW context (don't use request context)\n    go func() {\n        bgCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n        defer cancel()\n        _ = s.notifier.SendOrderConfirmation(bgCtx, order)\n    }()\n    \n    return order, nil\n}"
      },
      {
        "title": "Goroutine Lifecycle Management",
        "body": "// ✅ Worker pool with errgroup\nfunc (w *Worker) ProcessBatch(ctx context.Context, items []Item) error {\n    g, ctx := errgroup.WithContext(ctx)\n    g.SetLimit(10) // Max 10 concurrent goroutines\n    \n    for _, item := range items {\n        item := item // Go < 1.22 loop variable capture\n        g.Go(func() error {\n            return w.processItem(ctx, item)\n        })\n    }\n    \n    return g.Wait()\n}\n\n// ✅ Long-running goroutine with shutdown\ntype Processor struct {\n    done chan struct{}\n    wg   sync.WaitGroup\n}\n\nfunc (p *Processor) Start(ctx context.Context) {\n    p.wg.Add(1)\n    go func() {\n        defer p.wg.Done()\n        ticker := time.NewTicker(5 * time.Second)\n        defer ticker.Stop()\n        \n        for {\n            select {\n            case <-ctx.Done():\n                return\n            case <-ticker.C:\n                p.process(ctx)\n            }\n        }\n    }()\n}\n\nfunc (p *Processor) Stop() {\n    p.wg.Wait()\n}"
      },
      {
        "title": "Common Concurrency Pitfalls",
        "body": "PitfallSymptomFixGoroutine leakMemory grows foreverAlways have a termination path (context, done channel)Race condition-race flag failuresUse sync.Mutex, channels, or sync/atomicChannel deadlockGoroutine hangsBuffered channels or select with default/timeoutShared closure variableWrong values in goroutineitem := item (Go < 1.22) or use function paramsMissing sync.WaitGroupGoroutines outlive callerwg.Add before go, wg.Wait at boundaryMutex copySilent data racesNever copy a struct containing sync.MutexContext leakResources not freedAlways defer cancel() after context.WithCancel/Timeout\n\n6 Concurrency Rules:\n\nAlways run tests with -race flag\nerrgroup > manual goroutine + WaitGroup for bounded work\nChannels for communication, mutexes for state protection — pick one per use case\nNever start a goroutine without a plan for how it stops\nUse context.Background() for fire-and-forget, NEVER the request context\nsync.Once for one-time initialization (DB connections, configs)"
      },
      {
        "title": "Consumer-Defined Interfaces (Go Convention)",
        "body": "// ❌ BAD: Defining interface where implemented\n// repository/user.go\ntype UserRepository interface { // Don't define here\n    GetByID(ctx context.Context, id string) (*User, error)\n    Create(ctx context.Context, user *User) error\n}\n\n// ✅ GOOD: Define interface where consumed\n// service/user.go\ntype userRepository interface { // Private — only this package uses it\n    GetByID(ctx context.Context, id string) (*domain.User, error)\n    Create(ctx context.Context, user *domain.User) error\n}\n\ntype UserService struct {\n    repo   userRepository\n    logger *slog.Logger\n}\n\nfunc NewUserService(repo userRepository, logger *slog.Logger) *UserService {\n    return &UserService{repo: repo, logger: logger}\n}\n\nInterface Rules:\n\nAccept interfaces, return structs\nKeep interfaces small — 1-3 methods ideal\nName interfaces by what they do: Reader, Storer, Notifier — not IUser or UserInterface\nThe empty interface (any) means you've given up on type safety — use sparingly\nInterfaces are satisfied implicitly — no implements keyword needed (duck typing)"
      },
      {
        "title": "Table-Driven Tests (The Go Way)",
        "body": "func TestUserService_Create(t *testing.T) {\n    tests := []struct {\n        name    string\n        input   CreateUserRequest\n        setup   func(*mockUserRepo)\n        want    *domain.User\n        wantErr error\n    }{\n        {\n            name:  \"success\",\n            input: CreateUserRequest{Name: \"Alice\", Email: \"alice@example.com\"},\n            setup: func(m *mockUserRepo) {\n                m.On(\"Create\", mock.Anything, mock.AnythingOfType(\"*domain.User\")).Return(nil)\n            },\n            want: &domain.User{Name: \"Alice\", Email: \"alice@example.com\"},\n        },\n        {\n            name:  \"duplicate email\",\n            input: CreateUserRequest{Name: \"Alice\", Email: \"existing@example.com\"},\n            setup: func(m *mockUserRepo) {\n                m.On(\"Create\", mock.Anything, mock.Anything).Return(domain.ErrConflict)\n            },\n            wantErr: domain.ErrConflict,\n        },\n        {\n            name:    \"empty name\",\n            input:   CreateUserRequest{Name: \"\", Email: \"alice@example.com\"},\n            wantErr: domain.ErrValidation,\n        },\n    }\n    \n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            repo := new(mockUserRepo)\n            if tt.setup != nil {\n                tt.setup(repo)\n            }\n            \n            svc := NewUserService(repo, slog.Default())\n            got, err := svc.Create(context.Background(), tt.input)\n            \n            if tt.wantErr != nil {\n                assert.ErrorIs(t, err, tt.wantErr)\n                return\n            }\n            require.NoError(t, err)\n            assert.Equal(t, tt.want.Name, got.Name)\n            assert.Equal(t, tt.want.Email, got.Email)\n        })\n    }\n}"
      },
      {
        "title": "Test Categories & Targets",
        "body": "CategoryTargetToolsLocationUnit>80% of service/domaintestify, mockery*_test.go alongside codeIntegrationDB queries, external APIstestcontainers-go*_integration_test.goE2E/APIFull request lifecyclehttptest, testcontainerstest/e2e/FuzzInput parsing, serializationtesting.F (stdlib)*_test.goBenchmarkHot paths, serializationtesting.B (stdlib)*_test.go"
      },
      {
        "title": "Integration Testing with testcontainers",
        "body": "func TestUserRepository_Integration(t *testing.T) {\n    if testing.Short() {\n        t.Skip(\"skipping integration test\")\n    }\n    \n    ctx := context.Background()\n    \n    pg, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{\n        ContainerRequest: testcontainers.ContainerRequest{\n            Image:        \"postgres:16-alpine\",\n            ExposedPorts: []string{\"5432/tcp\"},\n            Env: map[string]string{\n                \"POSTGRES_PASSWORD\": \"test\",\n                \"POSTGRES_DB\":       \"testdb\",\n            },\n            WaitingFor: wait.ForListeningPort(\"5432/tcp\"),\n        },\n        Started: true,\n    })\n    require.NoError(t, err)\n    defer pg.Terminate(ctx)\n    \n    connStr, _ := pg.ConnectionString(ctx, \"sslmode=disable\")\n    db := pgx.MustConnect(ctx, connStr)\n    runMigrations(db)\n    \n    repo := NewUserRepository(db)\n    \n    t.Run(\"create and get\", func(t *testing.T) {\n        user := &domain.User{Name: \"Test\", Email: \"test@example.com\"}\n        err := repo.Create(ctx, user)\n        require.NoError(t, err)\n        \n        got, err := repo.GetByID(ctx, user.ID)\n        require.NoError(t, err)\n        assert.Equal(t, user.Name, got.Name)\n    })\n}\n\n7 Testing Rules:\n\n-race flag in ALL test runs: go test -race ./...\nTable-driven tests for anything with >2 cases\ntestcontainers-go for integration tests (real DB, real Redis)\nUse t.Parallel() where safe — Go tests run sequentially by default\ntesting.Short() to skip slow tests: go test -short ./...\nFuzz critical parsing code: func FuzzParseInput(f *testing.F)\nBenchmark hot paths: func BenchmarkSerialize(b *testing.B)"
      },
      {
        "title": "12-Factor Configuration",
        "body": "// internal/config/config.go\npackage config\n\nimport (\n    \"fmt\"\n    \"time\"\n    \"github.com/kelseyhightower/envconfig\"\n)\n\ntype Config struct {\n    Server   ServerConfig\n    Database DatabaseConfig\n    Redis    RedisConfig\n    Log      LogConfig\n}\n\ntype ServerConfig struct {\n    Addr         string        `envconfig:\"SERVER_ADDR\" default:\":8080\"`\n    ReadTimeout  time.Duration `envconfig:\"SERVER_READ_TIMEOUT\" default:\"5s\"`\n    WriteTimeout time.Duration `envconfig:\"SERVER_WRITE_TIMEOUT\" default:\"10s\"`\n    IdleTimeout  time.Duration `envconfig:\"SERVER_IDLE_TIMEOUT\" default:\"120s\"`\n}\n\ntype DatabaseConfig struct {\n    URL             string        `envconfig:\"DATABASE_URL\" required:\"true\"`\n    MaxConns        int           `envconfig:\"DATABASE_MAX_CONNS\" default:\"25\"`\n    MinConns        int           `envconfig:\"DATABASE_MIN_CONNS\" default:\"5\"`\n    MaxConnLifetime time.Duration `envconfig:\"DATABASE_MAX_CONN_LIFETIME\" default:\"1h\"`\n}\n\ntype RedisConfig struct {\n    URL          string        `envconfig:\"REDIS_URL\" default:\"localhost:6379\"`\n    MaxRetries   int           `envconfig:\"REDIS_MAX_RETRIES\" default:\"3\"`\n    DialTimeout  time.Duration `envconfig:\"REDIS_DIAL_TIMEOUT\" default:\"5s\"`\n    ReadTimeout  time.Duration `envconfig:\"REDIS_READ_TIMEOUT\" default:\"3s\"`\n    WriteTimeout time.Duration `envconfig:\"REDIS_WRITE_TIMEOUT\" default:\"3s\"`\n}\n\ntype LogConfig struct {\n    Level  string `envconfig:\"LOG_LEVEL\" default:\"info\"`\n    Format string `envconfig:\"LOG_FORMAT\" default:\"json\"` // json | text\n}\n\nfunc MustLoad() *Config {\n    var cfg Config\n    if err := envconfig.Process(\"\", &cfg); err != nil {\n        panic(fmt.Sprintf(\"config: %v\", err))\n    }\n    return &cfg\n}\n\nConfiguration Rules:\n\nValidate ALL config at startup — fail fast, not at 3 AM\nUse envconfig or viper — no scattered os.Getenv() calls\nProvide sensible defaults for non-secret values\nrequired:\"true\" for secrets and connection strings\nNever log secrets — redact in String() methods"
      },
      {
        "title": "slog (Go 1.21+ stdlib)",
        "body": "// internal/logging/logger.go\npackage logging\n\nimport (\n    \"log/slog\"\n    \"os\"\n)\n\nfunc New(cfg LogConfig) *slog.Logger {\n    var handler slog.Handler\n    \n    opts := &slog.HandlerOptions{\n        Level: parseLevel(cfg.Level),\n    }\n    \n    switch cfg.Format {\n    case \"text\":\n        handler = slog.NewTextHandler(os.Stdout, opts)\n    default:\n        handler = slog.NewJSONHandler(os.Stdout, opts)\n    }\n    \n    return slog.New(handler)\n}\n\n// Usage in services\nfunc (s *OrderService) Create(ctx context.Context, req CreateOrderRequest) (*Order, error) {\n    s.logger.InfoContext(ctx, \"creating order\",\n        \"user_id\", req.UserID,\n        \"items\", len(req.Items),\n    )\n    \n    order, err := s.repo.Create(ctx, req)\n    if err != nil {\n        s.logger.ErrorContext(ctx, \"order creation failed\",\n            \"user_id\", req.UserID,\n            \"error\", err,\n        )\n        return nil, fmt.Errorf(\"create order: %w\", err)\n    }\n    \n    s.logger.InfoContext(ctx, \"order created\",\n        \"order_id\", order.ID,\n        \"total\", order.Total,\n    )\n    return order, nil\n}"
      },
      {
        "title": "Request ID Middleware",
        "body": "func RequestIDMiddleware(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        requestID := r.Header.Get(\"X-Request-ID\")\n        if requestID == \"\" {\n            requestID = uuid.NewString()\n        }\n        \n        ctx := context.WithValue(r.Context(), requestIDKey, requestID)\n        w.Header().Set(\"X-Request-ID\", requestID)\n        \n        // Add to logger context\n        logger := slog.Default().With(\"request_id\", requestID)\n        ctx = context.WithValue(ctx, loggerKey, logger)\n        \n        next.ServeHTTP(w, r.WithContext(ctx))\n    })\n}\n\nLog Level Guide:\n\nLevelWhenExampleDEBUGDevelopment tracingSQL queries, cache hits/missesINFOBusiness eventsOrder created, user registeredWARNRecoverable issuesRetry succeeded, deprecated API usedERRORFailed operationsDB connection lost, external API 500"
      },
      {
        "title": "pgx Connection Pool",
        "body": "func MustConnect(cfg DatabaseConfig) *pgxpool.Pool {\n    poolCfg, err := pgxpool.ParseConfig(cfg.URL)\n    if err != nil {\n        panic(fmt.Sprintf(\"parse db config: %v\", err))\n    }\n    \n    poolCfg.MaxConns = int32(cfg.MaxConns)\n    poolCfg.MinConns = int32(cfg.MinConns)\n    poolCfg.MaxConnLifetime = cfg.MaxConnLifetime\n    poolCfg.HealthCheckPeriod = 30 * time.Second\n    \n    pool, err := pgxpool.NewWithConfig(context.Background(), poolCfg)\n    if err != nil {\n        panic(fmt.Sprintf(\"connect db: %v\", err))\n    }\n    \n    if err := pool.Ping(context.Background()); err != nil {\n        panic(fmt.Sprintf(\"ping db: %v\", err))\n    }\n    \n    return pool\n}"
      },
      {
        "title": "sqlc Pattern (Type-Safe SQL)",
        "body": "-- queries/user.sql\n-- name: GetUser :one\nSELECT id, name, email, created_at FROM users WHERE id = $1;\n\n-- name: ListUsers :many\nSELECT id, name, email, created_at FROM users\nWHERE ($1::text IS NULL OR name ILIKE '%' || $1 || '%')\nORDER BY created_at DESC\nLIMIT $2 OFFSET $3;\n\n-- name: CreateUser :one\nINSERT INTO users (name, email) VALUES ($1, $2)\nRETURNING id, name, email, created_at;\n\n# sqlc.yaml\nversion: \"2\"\nsql:\n  - engine: \"postgresql\"\n    queries: \"queries/\"\n    schema: \"migrations/\"\n    gen:\n      go:\n        package: \"db\"\n        out: \"internal/repository/db\"\n        sql_package: \"pgx/v5\"\n        emit_json_tags: true\n        emit_empty_slices: true"
      },
      {
        "title": "Transaction Pattern",
        "body": "func (r *OrderRepo) CreateWithItems(ctx context.Context, order *Order, items []Item) error {\n    tx, err := r.pool.Begin(ctx)\n    if err != nil {\n        return fmt.Errorf(\"begin tx: %w\", err)\n    }\n    defer tx.Rollback(ctx) // No-op if committed\n    \n    if err := r.queries.WithTx(tx).CreateOrder(ctx, order); err != nil {\n        return fmt.Errorf(\"create order: %w\", err)\n    }\n    \n    for _, item := range items {\n        if err := r.queries.WithTx(tx).CreateOrderItem(ctx, item); err != nil {\n            return fmt.Errorf(\"create item: %w\", err)\n        }\n    }\n    \n    if err := tx.Commit(ctx); err != nil {\n        return fmt.Errorf(\"commit: %w\", err)\n    }\n    return nil\n}"
      },
      {
        "title": "Router Setup with chi",
        "body": "func NewRouter(userSvc *service.UserService, logger *slog.Logger) http.Handler {\n    r := chi.NewRouter()\n    \n    // Middleware stack (order matters)\n    r.Use(middleware.RequestID)\n    r.Use(middleware.RealIP)\n    r.Use(RequestLoggerMiddleware(logger))\n    r.Use(middleware.Recoverer)\n    r.Use(middleware.Timeout(30 * time.Second))\n    r.Use(CORSMiddleware)\n    \n    // Health checks (no auth)\n    r.Get(\"/healthz\", healthCheck)\n    r.Get(\"/readyz\", readinessCheck)\n    \n    // API v1\n    r.Route(\"/api/v1\", func(r chi.Router) {\n        r.Use(AuthMiddleware)\n        \n        r.Route(\"/users\", func(r chi.Router) {\n            r.Get(\"/\", listUsers(userSvc))\n            r.Post(\"/\", createUser(userSvc))\n            r.Route(\"/{id}\", func(r chi.Router) {\n                r.Get(\"/\", getUser(userSvc))\n                r.Put(\"/\", updateUser(userSvc))\n                r.Delete(\"/\", deleteUser(userSvc))\n            })\n        })\n    })\n    \n    return r\n}"
      },
      {
        "title": "Request/Response Pattern",
        "body": "func createUser(svc *service.UserService) http.HandlerFunc {\n    type request struct {\n        Name  string `json:\"name\" validate:\"required,min=2,max=100\"`\n        Email string `json:\"email\" validate:\"required,email\"`\n    }\n    \n    type response struct {\n        ID        string    `json:\"id\"`\n        Name      string    `json:\"name\"`\n        Email     string    `json:\"email\"`\n        CreatedAt time.Time `json:\"created_at\"`\n    }\n    \n    return func(w http.ResponseWriter, r *http.Request) {\n        var req request\n        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {\n            respondError(w, http.StatusBadRequest, \"invalid JSON\")\n            return\n        }\n        \n        if err := validate.Struct(req); err != nil {\n            respondError(w, http.StatusBadRequest, formatValidation(err))\n            return\n        }\n        \n        user, err := svc.Create(r.Context(), service.CreateUserRequest{\n            Name:  req.Name,\n            Email: req.Email,\n        })\n        if err != nil {\n            code, msg := mapError(err)\n            respondError(w, code, msg)\n            return\n        }\n        \n        respondJSON(w, http.StatusCreated, response{\n            ID:        user.ID,\n            Name:      user.Name,\n            Email:     user.Email,\n            CreatedAt: user.CreatedAt,\n        })\n    }\n}\n\nfunc respondJSON(w http.ResponseWriter, code int, data any) {\n    w.Header().Set(\"Content-Type\", \"application/json\")\n    w.WriteHeader(code)\n    json.NewEncoder(w).Encode(data)\n}\n\nfunc respondError(w http.ResponseWriter, code int, message string) {\n    respondJSON(w, code, map[string]string{\"error\": message})\n}"
      },
      {
        "title": "Health Check Pattern",
        "body": "func healthCheck(w http.ResponseWriter, r *http.Request) {\n    respondJSON(w, http.StatusOK, map[string]string{\"status\": \"ok\"})\n}\n\nfunc readinessCheck(db *pgxpool.Pool, redis *redis.Client) http.HandlerFunc {\n    return func(w http.ResponseWriter, r *http.Request) {\n        ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)\n        defer cancel()\n        \n        checks := map[string]string{}\n        healthy := true\n        \n        if err := db.Ping(ctx); err != nil {\n            checks[\"database\"] = \"unhealthy\"\n            healthy = false\n        } else {\n            checks[\"database\"] = \"healthy\"\n        }\n        \n        if err := redis.Ping(ctx).Err(); err != nil {\n            checks[\"redis\"] = \"unhealthy\"\n            healthy = false\n        } else {\n            checks[\"redis\"] = \"healthy\"\n        }\n        \n        code := http.StatusOK\n        if !healthy {\n            code = http.StatusServiceUnavailable\n        }\n        respondJSON(w, code, checks)\n    }\n}"
      },
      {
        "title": "OTel Setup",
        "body": "func initTracer(ctx context.Context, serviceName string) (*sdktrace.TracerProvider, error) {\n    exporter, err := otlptracehttp.New(ctx)\n    if err != nil {\n        return nil, fmt.Errorf(\"create exporter: %w\", err)\n    }\n    \n    tp := sdktrace.NewTracerProvider(\n        sdktrace.WithBatcher(exporter),\n        sdktrace.WithResource(resource.NewWithAttributes(\n            semconv.SchemaURL,\n            semconv.ServiceName(serviceName),\n            semconv.ServiceVersion(\"1.0.0\"),\n        )),\n        sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(0.1))),\n    )\n    \n    otel.SetTracerProvider(tp)\n    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(\n        propagation.TraceContext{},\n        propagation.Baggage{},\n    ))\n    \n    return tp, nil\n}"
      },
      {
        "title": "Metrics with Prometheus",
        "body": "var (\n    httpRequestsTotal = promauto.NewCounterVec(\n        prometheus.CounterOpts{\n            Name: \"http_requests_total\",\n            Help: \"Total HTTP requests\",\n        },\n        []string{\"method\", \"path\", \"status\"},\n    )\n    \n    httpRequestDuration = promauto.NewHistogramVec(\n        prometheus.HistogramOpts{\n            Name:    \"http_request_duration_seconds\",\n            Help:    \"HTTP request duration\",\n            Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5},\n        },\n        []string{\"method\", \"path\"},\n    )\n)\n\nfunc MetricsMiddleware(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        start := time.Now()\n        ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)\n        \n        next.ServeHTTP(ww, r)\n        \n        duration := time.Since(start).Seconds()\n        path := chi.RouteContext(r.Context()).RoutePattern()\n        \n        httpRequestsTotal.WithLabelValues(r.Method, path, strconv.Itoa(ww.Status())).Inc()\n        httpRequestDuration.WithLabelValues(r.Method, path).Observe(duration)\n    })\n}"
      },
      {
        "title": "Multi-Stage Dockerfile",
        "body": "# Build stage\nFROM golang:1.23-alpine AS builder\n\nRUN apk add --no-cache git ca-certificates\n\nWORKDIR /app\n\nCOPY go.mod go.sum ./\nRUN go mod download\n\nCOPY . .\n\nRUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \\\n    go build -ldflags=\"-w -s -X main.version=$(git describe --tags --always)\" \\\n    -o /app/server ./cmd/api\n\n# Runtime stage\nFROM scratch\n\nCOPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/\nCOPY --from=builder /app/server /server\nCOPY --from=builder /app/migrations /migrations\n\nUSER 65534:65534\n\nEXPOSE 8080\n\nENTRYPOINT [\"/server\"]"
      },
      {
        "title": "Makefile",
        "body": ".PHONY: build test lint run migrate\n\nBINARY := server\nVERSION := $(shell git describe --tags --always --dirty)\n\nbuild:\n\tCGO_ENABLED=0 go build -ldflags=\"-w -s -X main.version=$(VERSION)\" -o bin/$(BINARY) ./cmd/api\n\ntest:\n\tgo test -race -coverprofile=coverage.out ./...\n\tgo tool cover -func=coverage.out\n\ntest-short:\n\tgo test -race -short ./...\n\nlint:\n\tgolangci-lint run\n\nrun:\n\tgo run ./cmd/api\n\nmigrate-up:\n\tgoose -dir migrations postgres \"$(DATABASE_URL)\" up\n\nmigrate-down:\n\tgoose -dir migrations postgres \"$(DATABASE_URL)\" down\n\nmigrate-create:\n\tgoose -dir migrations create $(NAME) sql\n\ngenerate:\n\tsqlc generate\n\tmockery\n\ndocker-build:\n\tdocker build -t $(BINARY):$(VERSION) .\n\nci: lint test build"
      },
      {
        "title": "golangci-lint Configuration",
        "body": "# .golangci.yml\nrun:\n  timeout: 5m\n\nlinters:\n  enable:\n    - errcheck\n    - govet\n    - staticcheck\n    - unused\n    - gosimple\n    - ineffassign\n    - typecheck\n    - gocritic\n    - gofumpt\n    - revive\n    - misspell\n    - prealloc\n    - noctx         # Finds HTTP requests without context\n    - bodyclose     # Checks HTTP response body is closed\n    - sqlclosecheck # Checks sql.Rows is closed\n    - contextcheck  # Checks function whether use a non-inherited context\n    - errname       # Checks sentinel error names follow Go convention\n    - exhaustive    # Checks exhaustiveness of enum switch statements\n    - gosec         # Security-oriented linting\n    - nilerr        # Finds code returning nil even on error\n    - unparam       # Reports unused function parameters\n\nlinters-settings:\n  gocritic:\n    enabled-tags:\n      - diagnostic\n      - style\n      - performance\n  revive:\n    rules:\n      - name: unexported-return\n        disabled: true\n  gosec:\n    excludes:\n      - G104 # Unhandled errors — covered by errcheck\n\nissues:\n  exclude-rules:\n    - path: _test\\.go\n      linters:\n        - gosec\n        - errcheck"
      },
      {
        "title": "GitHub Actions CI",
        "body": "name: CI\non:\n  push:\n    branches: [main]\n  pull_request:\n\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    \n    services:\n      postgres:\n        image: postgres:16-alpine\n        env:\n          POSTGRES_PASSWORD: test\n          POSTGRES_DB: testdb\n        ports:\n          - 5432:5432\n        options: >-\n          --health-cmd pg_isready\n          --health-interval 10s\n          --health-timeout 5s\n          --health-retries 5\n    \n    steps:\n      - uses: actions/checkout@v4\n      \n      - uses: actions/setup-go@v5\n        with:\n          go-version: '1.23'\n      \n      - name: Lint\n        uses: golangci/golangci-lint-action@v6\n        with:\n          version: latest\n      \n      - name: Test\n        run: go test -race -coverprofile=coverage.out ./...\n        env:\n          DATABASE_URL: postgres://postgres:test@localhost:5432/testdb?sslmode=disable\n      \n      - name: Coverage\n        run: |\n          COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}')\n          echo \"Coverage: $COVERAGE\"\n      \n      - name: Build\n        run: go build -o /dev/null ./..."
      },
      {
        "title": "Priority Stack",
        "body": "PriorityTechniqueImpact1Connection pooling (pgx pool, HTTP client reuse)10-50x2Avoid unnecessary allocations (sync.Pool, pre-allocated slices)2-5x3Use strings.Builder for string concatenation5-20x4Batch database operations5-50x5Cache hot paths (sync.Map, local cache, Redis)10-100x6Profile before optimizing (pprof)—"
      },
      {
        "title": "Profiling",
        "body": "import _ \"net/http/pprof\"\n\n// In main.go (debug server on separate port)\ngo func() {\n    log.Println(http.ListenAndServe(\":6060\", nil))\n}()\n\n// Then: go tool pprof http://localhost:6060/debug/pprof/heap\n// Or:   go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30"
      },
      {
        "title": "Common Optimizations",
        "body": "// ✅ Pre-allocate slices when length is known\nusers := make([]User, 0, len(ids))\n\n// ✅ strings.Builder for concatenation\nvar b strings.Builder\nb.Grow(estimatedLen)\nfor _, s := range parts {\n    b.WriteString(s)\n}\nresult := b.String()\n\n// ✅ Reuse HTTP clients (never create per-request)\nvar httpClient = &http.Client{\n    Timeout: 10 * time.Second,\n    Transport: &http.Transport{\n        MaxIdleConns:        100,\n        MaxIdleConnsPerHost: 10,\n        IdleConnTimeout:     90 * time.Second,\n    },\n}\n\n// ✅ sync.Pool for frequently allocated objects\nvar bufPool = sync.Pool{\n    New: func() any {\n        return new(bytes.Buffer)\n    },\n}\n\nfunc process() {\n    buf := bufPool.Get().(*bytes.Buffer)\n    defer func() {\n        buf.Reset()\n        bufPool.Put(buf)\n    }()\n    // use buf...\n}"
      },
      {
        "title": "Security Checklist",
        "body": "CategoryCheckPriorityInputValidate all input with validator/v10P0SQLUse parameterized queries (sqlc/pgx) — NEVER string concatP0AuthJWT validation with proper key rotationP0SecretsEnvironment variables only, never hardcodedP0Dependenciesgovulncheck in CI, go mod tidy regularlyP1CORSStrict origin allowlist, not *P1Rate limitingPer-IP and per-user limitsP1HeadersSecurity headers middlewareP1TLSTLS 1.2+ only, strong ciphersP1LoggingNever log secrets, PII, or tokensP2"
      },
      {
        "title": "Security Headers Middleware",
        "body": "func SecurityHeaders(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        w.Header().Set(\"X-Content-Type-Options\", \"nosniff\")\n        w.Header().Set(\"X-Frame-Options\", \"DENY\")\n        w.Header().Set(\"X-XSS-Protection\", \"0\")\n        w.Header().Set(\"Strict-Transport-Security\", \"max-age=63072000; includeSubDomains\")\n        w.Header().Set(\"Content-Security-Policy\", \"default-src 'none'\")\n        w.Header().Set(\"Referrer-Policy\", \"strict-origin-when-cross-origin\")\n        next.ServeHTTP(w, r)\n    })\n}"
      },
      {
        "title": "Vulnerability Scanning",
        "body": "# Install\ngo install golang.org/x/vuln/cmd/govulncheck@latest\n\n# Scan\ngovulncheck ./...\n\n# In CI — fail build on vulnerabilities\ngovulncheck -show verbose ./..."
      },
      {
        "title": "Generics (Go 1.18+)",
        "body": "// Generic result type\ntype Result[T any] struct {\n    Data  T\n    Error error\n}\n\n// Generic repository\ntype Repository[T any] interface {\n    GetByID(ctx context.Context, id string) (*T, error)\n    List(ctx context.Context, filter Filter) ([]T, error)\n    Create(ctx context.Context, entity *T) error\n    Update(ctx context.Context, entity *T) error\n    Delete(ctx context.Context, id string) error\n}\n\n// Generic pagination\ntype Page[T any] struct {\n    Items      []T    `json:\"items\"`\n    NextCursor string `json:\"next_cursor,omitempty\"`\n    HasMore    bool   `json:\"has_more\"`\n}"
      },
      {
        "title": "Functional Options Pattern",
        "body": "type ServerOption func(*Server)\n\nfunc WithAddr(addr string) ServerOption {\n    return func(s *Server) { s.addr = addr }\n}\n\nfunc WithTimeout(d time.Duration) ServerOption {\n    return func(s *Server) { s.timeout = d }\n}\n\nfunc WithLogger(l *slog.Logger) ServerOption {\n    return func(s *Server) { s.logger = l }\n}\n\nfunc NewServer(opts ...ServerOption) *Server {\n    s := &Server{\n        addr:    \":8080\",\n        timeout: 30 * time.Second,\n        logger:  slog.Default(),\n    }\n    for _, opt := range opts {\n        opt(s)\n    }\n    return s\n}"
      },
      {
        "title": "Graceful Degradation",
        "body": "// Circuit breaker pattern (simplified)\ntype CircuitBreaker struct {\n    failures   atomic.Int64\n    threshold  int64\n    resetAfter time.Duration\n    lastFail   atomic.Int64\n}\n\nfunc (cb *CircuitBreaker) Execute(fn func() error) error {\n    if cb.isOpen() {\n        return ErrCircuitOpen\n    }\n    \n    err := fn()\n    if err != nil {\n        cb.failures.Add(1)\n        cb.lastFail.Store(time.Now().UnixNano())\n        return err\n    }\n    \n    cb.failures.Store(0)\n    return nil\n}\n\nfunc (cb *CircuitBreaker) isOpen() bool {\n    if cb.failures.Load() < cb.threshold {\n        return false\n    }\n    // Allow retry after reset period\n    elapsed := time.Since(time.Unix(0, cb.lastFail.Load()))\n    return elapsed < cb.resetAfter\n}"
      },
      {
        "title": "10 Go Production Commandments",
        "body": "internal/ is the gatekeeper — hide implementation details aggressively\nErrors are values — wrap them, check them, never ignore them\n-race flag always — data races are silent killers\nInterfaces at the consumer — small, focused, implicit\nContext everywhere — first param for anything doing I/O\nerrgroup for goroutines — bounded concurrency, clean error handling\nsqlc over ORMs — type safety from actual SQL, zero runtime reflection\nProfile before optimizing — pprof doesn't lie, intuition does\nFail at startup — validate config, check connections, panic early\nGraceful shutdown — catch signals, drain connections, close cleanly"
      },
      {
        "title": "10 Common Go Mistakes",
        "body": "MistakeImpactFixGoroutine leakMemory exhaustionAlways have termination pathMissing error checkSilent failureserrcheck linterString concatenation in loopO(n²) allocationsstrings.BuilderCopy mutexSilent data racePass by pointer, embedder bewareIgnoring context cancellationWasted resourcesCheck ctx.Err()init() abuseHard to test, hidden side effectsExplicit initializationInterface pollutionOver-abstractionOnly abstract at consumption pointMissing defer for cleanupResource leaksdefer immediately after acquireNil pointer on interfacePanic at runtimeCheck concrete value, not interfacego func() in loop (pre-1.22)Wrong variable captureditem := item or func param"
      },
      {
        "title": "Mandatory (P0)",
        "body": "-race clean test suite\n >80% test coverage on business logic\n Structured logging (slog/zerolog)\n Graceful shutdown with signal handling\n Health check endpoints (/healthz, /readyz)\n Configuration validation at startup\n Error wrapping with context throughout\n golangci-lint clean (strict config)\n Multi-stage Docker build (scratch/distroless)\n govulncheck clean"
      },
      {
        "title": "Recommended (P1)",
        "body": "OpenTelemetry tracing\n Prometheus metrics\n Request ID propagation\n Rate limiting\n Security headers\n Integration tests with testcontainers\n Database migrations (goose/migrate)\n CI/CD pipeline (lint → test → build → deploy)"
      },
      {
        "title": "Quality Scoring (0-100)",
        "body": "DimensionWeightWhat to EvaluateError handling15%Wrapping, sentinels, no swallowed errorsConcurrency15%Race-free, context propagation, goroutine lifecycleTesting15%Coverage, table-driven, integration, -raceCode organization15%Package boundaries, internal/, dependency directionObservability10%Structured logging, metrics, tracingSecurity10%Input validation, govulncheck, secrets managementPerformance10%Profiling, pooling, pre-allocationDocumentation10%GoDoc, README, ADRs\n\nGrade: 0-40 = 🔴 Needs rewrite | 41-60 = 🟡 Significant gaps | 61-80 = 🟢 Production ready | 81-100 = 💎 Exemplary"
      },
      {
        "title": "Natural Language Commands",
        "body": "When asked about Go projects, interpret these naturally:\n\n\"Review this Go code\" → Run quick health check, identify anti-patterns\n\"Set up a new Go service\" → Generate full project structure with all phases\n\"Fix the error handling\" → Apply Phase 2 patterns throughout\n\"Add tests\" → Generate table-driven tests following Phase 5\n\"Make this production ready\" → Run through production readiness checklist\n\"Profile this\" → Guide through pprof analysis\n\"Add observability\" → Apply Phase 10 (OTel + Prometheus)\n\"Optimize performance\" → Profile first, then apply Phase 12 priority stack\n\"Set up CI\" → Generate GitHub Actions + golangci-lint config\n\"Add database\" → pgx pool + sqlc + migration setup\n\"Review architecture\" → Evaluate against Phase 1 rules\n\"Security audit\" → Run through Phase 13 checklist"
      }
    ],
    "body": "Go Production Engineering\n\nYou are a Go production engineering expert. Follow this system for every Go project — from architecture decisions through production deployment. Apply phases sequentially for new projects; use individual phases as needed for existing codebases.\n\nQuick Health Check (/16)\n\nScore 0 (missing), 1 (partial), or 2 (solid) for each signal:\n\nSignal\tWhat to Check\nProject structure\tStandard layout, clean package boundaries\nError handling\tWrapped errors, sentinel errors, no swallowed errors\nConcurrency safety\tNo goroutine leaks, proper context propagation\nTesting\t>80% coverage, table-driven tests, race detector clean\nObservability\tStructured logging, metrics, tracing\nConfiguration\t12-factor, validated at startup\nCI/CD\tLinting, testing, building in pipeline\nDocumentation\tGoDoc comments, README, ADRs\n\nScore interpretation: 0-6 = 🔴 Critical gaps | 7-10 = 🟡 Needs work | 11-14 = 🟢 Solid | 15-16 = 💎 Exemplary\n\nPhase 1: Project Architecture\nProject Structure (Standard Layout)\nproject-root/\n├── cmd/\n│   ├── api/              # HTTP API binary\n│   │   └── main.go\n│   └── worker/           # Background worker binary\n│       └── main.go\n├── internal/             # Private packages (enforced by Go)\n│   ├── domain/           # Business types & interfaces\n│   │   ├── user.go\n│   │   └── order.go\n│   ├── service/          # Business logic\n│   │   ├── user.go\n│   │   └── user_test.go\n│   ├── repository/       # Data access\n│   │   ├── postgres/\n│   │   └── redis/\n│   ├── handler/          # HTTP/gRPC handlers\n│   │   ├── http/\n│   │   └── grpc/\n│   ├── middleware/        # HTTP middleware\n│   └── config/           # Configuration\n├── pkg/                  # Public packages (use sparingly)\n├── api/                  # OpenAPI specs, proto files\n├── migrations/           # Database migrations\n├── scripts/              # Build/deploy scripts\n├── Makefile\n├── Dockerfile\n├── go.mod\n├── go.sum\n└── .golangci.yml\n\n\n7 Architecture Rules:\n\ninternal/ is your best friend — use it aggressively to prevent leaky abstractions\ncmd/ contains only main.go files — wire dependencies here, zero business logic\nDomain types live in internal/domain/ — no external dependencies allowed in this package\nInterfaces are defined by the consumer, not the implementer (Go convention)\nOne package = one responsibility. If you can't name it in one word, split it\nAvoid pkg/ unless you genuinely intend the package to be imported by other projects\nCircular imports are compile errors in Go — design your dependency graph as a DAG\nDependency Injection Pattern\n// cmd/api/main.go — wire everything here\nfunc main() {\n    cfg := config.MustLoad()\n    \n    // Infrastructure\n    db := postgres.MustConnect(cfg.Database)\n    cache := redis.MustConnect(cfg.Redis)\n    logger := logging.New(cfg.Log)\n    \n    // Repositories\n    userRepo := postgres.NewUserRepository(db)\n    orderRepo := postgres.NewOrderRepository(db)\n    \n    // Services\n    userSvc := service.NewUserService(userRepo, cache, logger)\n    orderSvc := service.NewOrderService(orderRepo, userSvc, logger)\n    \n    // Handlers\n    router := handler.NewRouter(userSvc, orderSvc, logger)\n    \n    // Server\n    srv := &http.Server{\n        Addr:         cfg.Server.Addr,\n        Handler:      router,\n        ReadTimeout:  cfg.Server.ReadTimeout,\n        WriteTimeout: cfg.Server.WriteTimeout,\n        IdleTimeout:  cfg.Server.IdleTimeout,\n    }\n    \n    // Graceful shutdown\n    go func() {\n        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {\n            logger.Fatal(\"server failed\", \"error\", err)\n        }\n    }()\n    \n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n    <-quit\n    \n    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n    defer cancel()\n    \n    if err := srv.Shutdown(ctx); err != nil {\n        logger.Fatal(\"forced shutdown\", \"error\", err)\n    }\n}\n\nFramework & Library Selection\nCategory\tRecommended\tAlternative\tAvoid\nHTTP Router\tchi, echo\tgin, fiber\tnet/http alone for APIs\nDatabase\tpgx (Postgres), sqlc\tGORM, ent\tdatabase/sql directly\nMigrations\tgoose, golang-migrate\tatlas\tmanual SQL files\nConfig\tviper, envconfig\tkoanf\tos.Getenv scattered\nLogging\tslog (stdlib), zerolog\tzap\tlog (stdlib)\nTesting\ttestify, is\tgomock, mockery\tcustom assert helpers\nValidation\tvalidator/v10\tozzo-validation\tmanual if-checks\nCLI\tcobra\turfave/cli\tflag (stdlib) alone\ngRPC\tgoogle.golang.org/grpc\tconnect-go\t—\nObservability\tOTel SDK\tprometheus client\tcustom metrics\n\nSelection Rules:\n\nPrefer stdlib when it's good enough (slog, net/http for simple services, encoding/json)\npgx > database/sql for Postgres (performance, features, pgx pool)\nsqlc generates type-safe code from SQL — prefer over ORMs for query-heavy apps\nUse chi for REST APIs (stdlib-compatible, middleware ecosystem)\nFor gRPC, use connect-go if you want both gRPC and HTTP/JSON from one definition\nPhase 2: Error Handling\nError Architecture\n// internal/domain/errors.go — sentinel errors\npackage domain\n\nimport \"errors\"\n\nvar (\n    ErrNotFound      = errors.New(\"not found\")\n    ErrConflict      = errors.New(\"conflict\")\n    ErrUnauthorized  = errors.New(\"unauthorized\")\n    ErrForbidden     = errors.New(\"forbidden\")\n    ErrValidation    = errors.New(\"validation error\")\n    ErrInternal      = errors.New(\"internal error\")\n)\n\n// Typed error with context\ntype ValidationError struct {\n    Field   string\n    Message string\n}\n\nfunc (e *ValidationError) Error() string {\n    return fmt.Sprintf(\"validation: %s — %s\", e.Field, e.Message)\n}\n\nfunc (e *ValidationError) Unwrap() error {\n    return ErrValidation\n}\n\nError Wrapping Rules\n// ✅ GOOD: Wrap with context using fmt.Errorf %w\nfunc (r *UserRepo) GetByID(ctx context.Context, id string) (*User, error) {\n    user, err := r.db.QueryRow(ctx, query, id)\n    if err != nil {\n        if errors.Is(err, pgx.ErrNoRows) {\n            return nil, fmt.Errorf(\"user %s: %w\", id, domain.ErrNotFound)\n        }\n        return nil, fmt.Errorf(\"get user %s: %w\", id, err)\n    }\n    return user, nil\n}\n\n// ❌ BAD: Swallowed error\nif err != nil {\n    log.Println(err) // logged but not returned — caller doesn't know it failed\n    return nil\n}\n\n// ❌ BAD: Bare return\nif err != nil {\n    return err // no context — impossible to debug in production\n}\n\n// ❌ BAD: String wrapping (breaks errors.Is/As)\nreturn fmt.Errorf(\"failed: %s\", err) // use %w, not %s or %v\n\n\n8 Error Handling Rules:\n\nAlways wrap errors with context: fmt.Errorf(\"doing X: %w\", err)\nUse %w verb — it preserves the error chain for errors.Is() and errors.As()\nDefine sentinel errors in the domain package for business-level errors\nHandle errors at the boundary (HTTP handler) — map to status codes there\nNever ignore errors: _ = f.Close() is a code smell. At minimum: defer func() { _ = f.Close() }()\nUse errors.Is() for sentinel comparisons, errors.As() for typed errors\nDon't log AND return an error — pick one (usually return; log at the top)\nPanics are for programmer errors only (impossible states) — never for runtime errors\nHTTP Error Response Mapping\nfunc mapError(err error) (int, string) {\n    switch {\n    case errors.Is(err, domain.ErrNotFound):\n        return http.StatusNotFound, \"resource not found\"\n    case errors.Is(err, domain.ErrConflict):\n        return http.StatusConflict, \"resource already exists\"\n    case errors.Is(err, domain.ErrUnauthorized):\n        return http.StatusUnauthorized, \"authentication required\"\n    case errors.Is(err, domain.ErrForbidden):\n        return http.StatusForbidden, \"insufficient permissions\"\n    case errors.Is(err, domain.ErrValidation):\n        var ve *domain.ValidationError\n        if errors.As(err, &ve) {\n            return http.StatusBadRequest, ve.Error()\n        }\n        return http.StatusBadRequest, \"invalid request\"\n    default:\n        return http.StatusInternalServerError, \"internal server error\"\n    }\n}\n\nPhase 3: Concurrency Patterns\nContext Propagation (Non-Negotiable)\n// Every function that does I/O takes context as first parameter\nfunc (s *OrderService) Create(ctx context.Context, req CreateOrderRequest) (*Order, error) {\n    // Check cancellation before expensive operations\n    select {\n    case <-ctx.Done():\n        return nil, ctx.Err()\n    default:\n    }\n    \n    user, err := s.userRepo.GetByID(ctx, req.UserID)\n    if err != nil {\n        return nil, fmt.Errorf(\"get user: %w\", err)\n    }\n    \n    order, err := s.orderRepo.Create(ctx, user, req)\n    if err != nil {\n        return nil, fmt.Errorf(\"create order: %w\", err)\n    }\n    \n    // Fire-and-forget with NEW context (don't use request context)\n    go func() {\n        bgCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n        defer cancel()\n        _ = s.notifier.SendOrderConfirmation(bgCtx, order)\n    }()\n    \n    return order, nil\n}\n\nGoroutine Lifecycle Management\n// ✅ Worker pool with errgroup\nfunc (w *Worker) ProcessBatch(ctx context.Context, items []Item) error {\n    g, ctx := errgroup.WithContext(ctx)\n    g.SetLimit(10) // Max 10 concurrent goroutines\n    \n    for _, item := range items {\n        item := item // Go < 1.22 loop variable capture\n        g.Go(func() error {\n            return w.processItem(ctx, item)\n        })\n    }\n    \n    return g.Wait()\n}\n\n// ✅ Long-running goroutine with shutdown\ntype Processor struct {\n    done chan struct{}\n    wg   sync.WaitGroup\n}\n\nfunc (p *Processor) Start(ctx context.Context) {\n    p.wg.Add(1)\n    go func() {\n        defer p.wg.Done()\n        ticker := time.NewTicker(5 * time.Second)\n        defer ticker.Stop()\n        \n        for {\n            select {\n            case <-ctx.Done():\n                return\n            case <-ticker.C:\n                p.process(ctx)\n            }\n        }\n    }()\n}\n\nfunc (p *Processor) Stop() {\n    p.wg.Wait()\n}\n\nCommon Concurrency Pitfalls\nPitfall\tSymptom\tFix\nGoroutine leak\tMemory grows forever\tAlways have a termination path (context, done channel)\nRace condition\t-race flag failures\tUse sync.Mutex, channels, or sync/atomic\nChannel deadlock\tGoroutine hangs\tBuffered channels or select with default/timeout\nShared closure variable\tWrong values in goroutine\titem := item (Go < 1.22) or use function params\nMissing sync.WaitGroup\tGoroutines outlive caller\twg.Add before go, wg.Wait at boundary\nMutex copy\tSilent data races\tNever copy a struct containing sync.Mutex\nContext leak\tResources not freed\tAlways defer cancel() after context.WithCancel/Timeout\n\n6 Concurrency Rules:\n\nAlways run tests with -race flag\nerrgroup > manual goroutine + WaitGroup for bounded work\nChannels for communication, mutexes for state protection — pick one per use case\nNever start a goroutine without a plan for how it stops\nUse context.Background() for fire-and-forget, NEVER the request context\nsync.Once for one-time initialization (DB connections, configs)\nPhase 4: Interface Design\nConsumer-Defined Interfaces (Go Convention)\n// ❌ BAD: Defining interface where implemented\n// repository/user.go\ntype UserRepository interface { // Don't define here\n    GetByID(ctx context.Context, id string) (*User, error)\n    Create(ctx context.Context, user *User) error\n}\n\n// ✅ GOOD: Define interface where consumed\n// service/user.go\ntype userRepository interface { // Private — only this package uses it\n    GetByID(ctx context.Context, id string) (*domain.User, error)\n    Create(ctx context.Context, user *domain.User) error\n}\n\ntype UserService struct {\n    repo   userRepository\n    logger *slog.Logger\n}\n\nfunc NewUserService(repo userRepository, logger *slog.Logger) *UserService {\n    return &UserService{repo: repo, logger: logger}\n}\n\n\nInterface Rules:\n\nAccept interfaces, return structs\nKeep interfaces small — 1-3 methods ideal\nName interfaces by what they do: Reader, Storer, Notifier — not IUser or UserInterface\nThe empty interface (any) means you've given up on type safety — use sparingly\nInterfaces are satisfied implicitly — no implements keyword needed (duck typing)\nPhase 5: Testing\nTable-Driven Tests (The Go Way)\nfunc TestUserService_Create(t *testing.T) {\n    tests := []struct {\n        name    string\n        input   CreateUserRequest\n        setup   func(*mockUserRepo)\n        want    *domain.User\n        wantErr error\n    }{\n        {\n            name:  \"success\",\n            input: CreateUserRequest{Name: \"Alice\", Email: \"alice@example.com\"},\n            setup: func(m *mockUserRepo) {\n                m.On(\"Create\", mock.Anything, mock.AnythingOfType(\"*domain.User\")).Return(nil)\n            },\n            want: &domain.User{Name: \"Alice\", Email: \"alice@example.com\"},\n        },\n        {\n            name:  \"duplicate email\",\n            input: CreateUserRequest{Name: \"Alice\", Email: \"existing@example.com\"},\n            setup: func(m *mockUserRepo) {\n                m.On(\"Create\", mock.Anything, mock.Anything).Return(domain.ErrConflict)\n            },\n            wantErr: domain.ErrConflict,\n        },\n        {\n            name:    \"empty name\",\n            input:   CreateUserRequest{Name: \"\", Email: \"alice@example.com\"},\n            wantErr: domain.ErrValidation,\n        },\n    }\n    \n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            repo := new(mockUserRepo)\n            if tt.setup != nil {\n                tt.setup(repo)\n            }\n            \n            svc := NewUserService(repo, slog.Default())\n            got, err := svc.Create(context.Background(), tt.input)\n            \n            if tt.wantErr != nil {\n                assert.ErrorIs(t, err, tt.wantErr)\n                return\n            }\n            require.NoError(t, err)\n            assert.Equal(t, tt.want.Name, got.Name)\n            assert.Equal(t, tt.want.Email, got.Email)\n        })\n    }\n}\n\nTest Categories & Targets\nCategory\tTarget\tTools\tLocation\nUnit\t>80% of service/domain\ttestify, mockery\t*_test.go alongside code\nIntegration\tDB queries, external APIs\ttestcontainers-go\t*_integration_test.go\nE2E/API\tFull request lifecycle\thttptest, testcontainers\ttest/e2e/\nFuzz\tInput parsing, serialization\ttesting.F (stdlib)\t*_test.go\nBenchmark\tHot paths, serialization\ttesting.B (stdlib)\t*_test.go\nIntegration Testing with testcontainers\nfunc TestUserRepository_Integration(t *testing.T) {\n    if testing.Short() {\n        t.Skip(\"skipping integration test\")\n    }\n    \n    ctx := context.Background()\n    \n    pg, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{\n        ContainerRequest: testcontainers.ContainerRequest{\n            Image:        \"postgres:16-alpine\",\n            ExposedPorts: []string{\"5432/tcp\"},\n            Env: map[string]string{\n                \"POSTGRES_PASSWORD\": \"test\",\n                \"POSTGRES_DB\":       \"testdb\",\n            },\n            WaitingFor: wait.ForListeningPort(\"5432/tcp\"),\n        },\n        Started: true,\n    })\n    require.NoError(t, err)\n    defer pg.Terminate(ctx)\n    \n    connStr, _ := pg.ConnectionString(ctx, \"sslmode=disable\")\n    db := pgx.MustConnect(ctx, connStr)\n    runMigrations(db)\n    \n    repo := NewUserRepository(db)\n    \n    t.Run(\"create and get\", func(t *testing.T) {\n        user := &domain.User{Name: \"Test\", Email: \"test@example.com\"}\n        err := repo.Create(ctx, user)\n        require.NoError(t, err)\n        \n        got, err := repo.GetByID(ctx, user.ID)\n        require.NoError(t, err)\n        assert.Equal(t, user.Name, got.Name)\n    })\n}\n\n\n7 Testing Rules:\n\n-race flag in ALL test runs: go test -race ./...\nTable-driven tests for anything with >2 cases\ntestcontainers-go for integration tests (real DB, real Redis)\nUse t.Parallel() where safe — Go tests run sequentially by default\ntesting.Short() to skip slow tests: go test -short ./...\nFuzz critical parsing code: func FuzzParseInput(f *testing.F)\nBenchmark hot paths: func BenchmarkSerialize(b *testing.B)\nPhase 6: Configuration & Startup\n12-Factor Configuration\n// internal/config/config.go\npackage config\n\nimport (\n    \"fmt\"\n    \"time\"\n    \"github.com/kelseyhightower/envconfig\"\n)\n\ntype Config struct {\n    Server   ServerConfig\n    Database DatabaseConfig\n    Redis    RedisConfig\n    Log      LogConfig\n}\n\ntype ServerConfig struct {\n    Addr         string        `envconfig:\"SERVER_ADDR\" default:\":8080\"`\n    ReadTimeout  time.Duration `envconfig:\"SERVER_READ_TIMEOUT\" default:\"5s\"`\n    WriteTimeout time.Duration `envconfig:\"SERVER_WRITE_TIMEOUT\" default:\"10s\"`\n    IdleTimeout  time.Duration `envconfig:\"SERVER_IDLE_TIMEOUT\" default:\"120s\"`\n}\n\ntype DatabaseConfig struct {\n    URL             string        `envconfig:\"DATABASE_URL\" required:\"true\"`\n    MaxConns        int           `envconfig:\"DATABASE_MAX_CONNS\" default:\"25\"`\n    MinConns        int           `envconfig:\"DATABASE_MIN_CONNS\" default:\"5\"`\n    MaxConnLifetime time.Duration `envconfig:\"DATABASE_MAX_CONN_LIFETIME\" default:\"1h\"`\n}\n\ntype RedisConfig struct {\n    URL          string        `envconfig:\"REDIS_URL\" default:\"localhost:6379\"`\n    MaxRetries   int           `envconfig:\"REDIS_MAX_RETRIES\" default:\"3\"`\n    DialTimeout  time.Duration `envconfig:\"REDIS_DIAL_TIMEOUT\" default:\"5s\"`\n    ReadTimeout  time.Duration `envconfig:\"REDIS_READ_TIMEOUT\" default:\"3s\"`\n    WriteTimeout time.Duration `envconfig:\"REDIS_WRITE_TIMEOUT\" default:\"3s\"`\n}\n\ntype LogConfig struct {\n    Level  string `envconfig:\"LOG_LEVEL\" default:\"info\"`\n    Format string `envconfig:\"LOG_FORMAT\" default:\"json\"` // json | text\n}\n\nfunc MustLoad() *Config {\n    var cfg Config\n    if err := envconfig.Process(\"\", &cfg); err != nil {\n        panic(fmt.Sprintf(\"config: %v\", err))\n    }\n    return &cfg\n}\n\n\nConfiguration Rules:\n\nValidate ALL config at startup — fail fast, not at 3 AM\nUse envconfig or viper — no scattered os.Getenv() calls\nProvide sensible defaults for non-secret values\nrequired:\"true\" for secrets and connection strings\nNever log secrets — redact in String() methods\nPhase 7: Structured Logging\nslog (Go 1.21+ stdlib)\n// internal/logging/logger.go\npackage logging\n\nimport (\n    \"log/slog\"\n    \"os\"\n)\n\nfunc New(cfg LogConfig) *slog.Logger {\n    var handler slog.Handler\n    \n    opts := &slog.HandlerOptions{\n        Level: parseLevel(cfg.Level),\n    }\n    \n    switch cfg.Format {\n    case \"text\":\n        handler = slog.NewTextHandler(os.Stdout, opts)\n    default:\n        handler = slog.NewJSONHandler(os.Stdout, opts)\n    }\n    \n    return slog.New(handler)\n}\n\n// Usage in services\nfunc (s *OrderService) Create(ctx context.Context, req CreateOrderRequest) (*Order, error) {\n    s.logger.InfoContext(ctx, \"creating order\",\n        \"user_id\", req.UserID,\n        \"items\", len(req.Items),\n    )\n    \n    order, err := s.repo.Create(ctx, req)\n    if err != nil {\n        s.logger.ErrorContext(ctx, \"order creation failed\",\n            \"user_id\", req.UserID,\n            \"error\", err,\n        )\n        return nil, fmt.Errorf(\"create order: %w\", err)\n    }\n    \n    s.logger.InfoContext(ctx, \"order created\",\n        \"order_id\", order.ID,\n        \"total\", order.Total,\n    )\n    return order, nil\n}\n\nRequest ID Middleware\nfunc RequestIDMiddleware(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        requestID := r.Header.Get(\"X-Request-ID\")\n        if requestID == \"\" {\n            requestID = uuid.NewString()\n        }\n        \n        ctx := context.WithValue(r.Context(), requestIDKey, requestID)\n        w.Header().Set(\"X-Request-ID\", requestID)\n        \n        // Add to logger context\n        logger := slog.Default().With(\"request_id\", requestID)\n        ctx = context.WithValue(ctx, loggerKey, logger)\n        \n        next.ServeHTTP(w, r.WithContext(ctx))\n    })\n}\n\n\nLog Level Guide:\n\nLevel\tWhen\tExample\nDEBUG\tDevelopment tracing\tSQL queries, cache hits/misses\nINFO\tBusiness events\tOrder created, user registered\nWARN\tRecoverable issues\tRetry succeeded, deprecated API used\nERROR\tFailed operations\tDB connection lost, external API 500\nPhase 8: Database Patterns\npgx Connection Pool\nfunc MustConnect(cfg DatabaseConfig) *pgxpool.Pool {\n    poolCfg, err := pgxpool.ParseConfig(cfg.URL)\n    if err != nil {\n        panic(fmt.Sprintf(\"parse db config: %v\", err))\n    }\n    \n    poolCfg.MaxConns = int32(cfg.MaxConns)\n    poolCfg.MinConns = int32(cfg.MinConns)\n    poolCfg.MaxConnLifetime = cfg.MaxConnLifetime\n    poolCfg.HealthCheckPeriod = 30 * time.Second\n    \n    pool, err := pgxpool.NewWithConfig(context.Background(), poolCfg)\n    if err != nil {\n        panic(fmt.Sprintf(\"connect db: %v\", err))\n    }\n    \n    if err := pool.Ping(context.Background()); err != nil {\n        panic(fmt.Sprintf(\"ping db: %v\", err))\n    }\n    \n    return pool\n}\n\nsqlc Pattern (Type-Safe SQL)\n-- queries/user.sql\n-- name: GetUser :one\nSELECT id, name, email, created_at FROM users WHERE id = $1;\n\n-- name: ListUsers :many\nSELECT id, name, email, created_at FROM users\nWHERE ($1::text IS NULL OR name ILIKE '%' || $1 || '%')\nORDER BY created_at DESC\nLIMIT $2 OFFSET $3;\n\n-- name: CreateUser :one\nINSERT INTO users (name, email) VALUES ($1, $2)\nRETURNING id, name, email, created_at;\n\n# sqlc.yaml\nversion: \"2\"\nsql:\n  - engine: \"postgresql\"\n    queries: \"queries/\"\n    schema: \"migrations/\"\n    gen:\n      go:\n        package: \"db\"\n        out: \"internal/repository/db\"\n        sql_package: \"pgx/v5\"\n        emit_json_tags: true\n        emit_empty_slices: true\n\nTransaction Pattern\nfunc (r *OrderRepo) CreateWithItems(ctx context.Context, order *Order, items []Item) error {\n    tx, err := r.pool.Begin(ctx)\n    if err != nil {\n        return fmt.Errorf(\"begin tx: %w\", err)\n    }\n    defer tx.Rollback(ctx) // No-op if committed\n    \n    if err := r.queries.WithTx(tx).CreateOrder(ctx, order); err != nil {\n        return fmt.Errorf(\"create order: %w\", err)\n    }\n    \n    for _, item := range items {\n        if err := r.queries.WithTx(tx).CreateOrderItem(ctx, item); err != nil {\n            return fmt.Errorf(\"create item: %w\", err)\n        }\n    }\n    \n    if err := tx.Commit(ctx); err != nil {\n        return fmt.Errorf(\"commit: %w\", err)\n    }\n    return nil\n}\n\nPhase 9: HTTP API Design\nRouter Setup with chi\nfunc NewRouter(userSvc *service.UserService, logger *slog.Logger) http.Handler {\n    r := chi.NewRouter()\n    \n    // Middleware stack (order matters)\n    r.Use(middleware.RequestID)\n    r.Use(middleware.RealIP)\n    r.Use(RequestLoggerMiddleware(logger))\n    r.Use(middleware.Recoverer)\n    r.Use(middleware.Timeout(30 * time.Second))\n    r.Use(CORSMiddleware)\n    \n    // Health checks (no auth)\n    r.Get(\"/healthz\", healthCheck)\n    r.Get(\"/readyz\", readinessCheck)\n    \n    // API v1\n    r.Route(\"/api/v1\", func(r chi.Router) {\n        r.Use(AuthMiddleware)\n        \n        r.Route(\"/users\", func(r chi.Router) {\n            r.Get(\"/\", listUsers(userSvc))\n            r.Post(\"/\", createUser(userSvc))\n            r.Route(\"/{id}\", func(r chi.Router) {\n                r.Get(\"/\", getUser(userSvc))\n                r.Put(\"/\", updateUser(userSvc))\n                r.Delete(\"/\", deleteUser(userSvc))\n            })\n        })\n    })\n    \n    return r\n}\n\nRequest/Response Pattern\nfunc createUser(svc *service.UserService) http.HandlerFunc {\n    type request struct {\n        Name  string `json:\"name\" validate:\"required,min=2,max=100\"`\n        Email string `json:\"email\" validate:\"required,email\"`\n    }\n    \n    type response struct {\n        ID        string    `json:\"id\"`\n        Name      string    `json:\"name\"`\n        Email     string    `json:\"email\"`\n        CreatedAt time.Time `json:\"created_at\"`\n    }\n    \n    return func(w http.ResponseWriter, r *http.Request) {\n        var req request\n        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {\n            respondError(w, http.StatusBadRequest, \"invalid JSON\")\n            return\n        }\n        \n        if err := validate.Struct(req); err != nil {\n            respondError(w, http.StatusBadRequest, formatValidation(err))\n            return\n        }\n        \n        user, err := svc.Create(r.Context(), service.CreateUserRequest{\n            Name:  req.Name,\n            Email: req.Email,\n        })\n        if err != nil {\n            code, msg := mapError(err)\n            respondError(w, code, msg)\n            return\n        }\n        \n        respondJSON(w, http.StatusCreated, response{\n            ID:        user.ID,\n            Name:      user.Name,\n            Email:     user.Email,\n            CreatedAt: user.CreatedAt,\n        })\n    }\n}\n\nfunc respondJSON(w http.ResponseWriter, code int, data any) {\n    w.Header().Set(\"Content-Type\", \"application/json\")\n    w.WriteHeader(code)\n    json.NewEncoder(w).Encode(data)\n}\n\nfunc respondError(w http.ResponseWriter, code int, message string) {\n    respondJSON(w, code, map[string]string{\"error\": message})\n}\n\nHealth Check Pattern\nfunc healthCheck(w http.ResponseWriter, r *http.Request) {\n    respondJSON(w, http.StatusOK, map[string]string{\"status\": \"ok\"})\n}\n\nfunc readinessCheck(db *pgxpool.Pool, redis *redis.Client) http.HandlerFunc {\n    return func(w http.ResponseWriter, r *http.Request) {\n        ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)\n        defer cancel()\n        \n        checks := map[string]string{}\n        healthy := true\n        \n        if err := db.Ping(ctx); err != nil {\n            checks[\"database\"] = \"unhealthy\"\n            healthy = false\n        } else {\n            checks[\"database\"] = \"healthy\"\n        }\n        \n        if err := redis.Ping(ctx).Err(); err != nil {\n            checks[\"redis\"] = \"unhealthy\"\n            healthy = false\n        } else {\n            checks[\"redis\"] = \"healthy\"\n        }\n        \n        code := http.StatusOK\n        if !healthy {\n            code = http.StatusServiceUnavailable\n        }\n        respondJSON(w, code, checks)\n    }\n}\n\nPhase 10: Observability (OpenTelemetry)\nOTel Setup\nfunc initTracer(ctx context.Context, serviceName string) (*sdktrace.TracerProvider, error) {\n    exporter, err := otlptracehttp.New(ctx)\n    if err != nil {\n        return nil, fmt.Errorf(\"create exporter: %w\", err)\n    }\n    \n    tp := sdktrace.NewTracerProvider(\n        sdktrace.WithBatcher(exporter),\n        sdktrace.WithResource(resource.NewWithAttributes(\n            semconv.SchemaURL,\n            semconv.ServiceName(serviceName),\n            semconv.ServiceVersion(\"1.0.0\"),\n        )),\n        sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(0.1))),\n    )\n    \n    otel.SetTracerProvider(tp)\n    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(\n        propagation.TraceContext{},\n        propagation.Baggage{},\n    ))\n    \n    return tp, nil\n}\n\nMetrics with Prometheus\nvar (\n    httpRequestsTotal = promauto.NewCounterVec(\n        prometheus.CounterOpts{\n            Name: \"http_requests_total\",\n            Help: \"Total HTTP requests\",\n        },\n        []string{\"method\", \"path\", \"status\"},\n    )\n    \n    httpRequestDuration = promauto.NewHistogramVec(\n        prometheus.HistogramOpts{\n            Name:    \"http_request_duration_seconds\",\n            Help:    \"HTTP request duration\",\n            Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5},\n        },\n        []string{\"method\", \"path\"},\n    )\n)\n\nfunc MetricsMiddleware(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        start := time.Now()\n        ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)\n        \n        next.ServeHTTP(ww, r)\n        \n        duration := time.Since(start).Seconds()\n        path := chi.RouteContext(r.Context()).RoutePattern()\n        \n        httpRequestsTotal.WithLabelValues(r.Method, path, strconv.Itoa(ww.Status())).Inc()\n        httpRequestDuration.WithLabelValues(r.Method, path).Observe(duration)\n    })\n}\n\nPhase 11: Production Deployment\nMulti-Stage Dockerfile\n# Build stage\nFROM golang:1.23-alpine AS builder\n\nRUN apk add --no-cache git ca-certificates\n\nWORKDIR /app\n\nCOPY go.mod go.sum ./\nRUN go mod download\n\nCOPY . .\n\nRUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \\\n    go build -ldflags=\"-w -s -X main.version=$(git describe --tags --always)\" \\\n    -o /app/server ./cmd/api\n\n# Runtime stage\nFROM scratch\n\nCOPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/\nCOPY --from=builder /app/server /server\nCOPY --from=builder /app/migrations /migrations\n\nUSER 65534:65534\n\nEXPOSE 8080\n\nENTRYPOINT [\"/server\"]\n\nMakefile\n.PHONY: build test lint run migrate\n\nBINARY := server\nVERSION := $(shell git describe --tags --always --dirty)\n\nbuild:\n\tCGO_ENABLED=0 go build -ldflags=\"-w -s -X main.version=$(VERSION)\" -o bin/$(BINARY) ./cmd/api\n\ntest:\n\tgo test -race -coverprofile=coverage.out ./...\n\tgo tool cover -func=coverage.out\n\ntest-short:\n\tgo test -race -short ./...\n\nlint:\n\tgolangci-lint run\n\nrun:\n\tgo run ./cmd/api\n\nmigrate-up:\n\tgoose -dir migrations postgres \"$(DATABASE_URL)\" up\n\nmigrate-down:\n\tgoose -dir migrations postgres \"$(DATABASE_URL)\" down\n\nmigrate-create:\n\tgoose -dir migrations create $(NAME) sql\n\ngenerate:\n\tsqlc generate\n\tmockery\n\ndocker-build:\n\tdocker build -t $(BINARY):$(VERSION) .\n\nci: lint test build\n\ngolangci-lint Configuration\n# .golangci.yml\nrun:\n  timeout: 5m\n\nlinters:\n  enable:\n    - errcheck\n    - govet\n    - staticcheck\n    - unused\n    - gosimple\n    - ineffassign\n    - typecheck\n    - gocritic\n    - gofumpt\n    - revive\n    - misspell\n    - prealloc\n    - noctx         # Finds HTTP requests without context\n    - bodyclose     # Checks HTTP response body is closed\n    - sqlclosecheck # Checks sql.Rows is closed\n    - contextcheck  # Checks function whether use a non-inherited context\n    - errname       # Checks sentinel error names follow Go convention\n    - exhaustive    # Checks exhaustiveness of enum switch statements\n    - gosec         # Security-oriented linting\n    - nilerr        # Finds code returning nil even on error\n    - unparam       # Reports unused function parameters\n\nlinters-settings:\n  gocritic:\n    enabled-tags:\n      - diagnostic\n      - style\n      - performance\n  revive:\n    rules:\n      - name: unexported-return\n        disabled: true\n  gosec:\n    excludes:\n      - G104 # Unhandled errors — covered by errcheck\n\nissues:\n  exclude-rules:\n    - path: _test\\.go\n      linters:\n        - gosec\n        - errcheck\n\nGitHub Actions CI\nname: CI\non:\n  push:\n    branches: [main]\n  pull_request:\n\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    \n    services:\n      postgres:\n        image: postgres:16-alpine\n        env:\n          POSTGRES_PASSWORD: test\n          POSTGRES_DB: testdb\n        ports:\n          - 5432:5432\n        options: >-\n          --health-cmd pg_isready\n          --health-interval 10s\n          --health-timeout 5s\n          --health-retries 5\n    \n    steps:\n      - uses: actions/checkout@v4\n      \n      - uses: actions/setup-go@v5\n        with:\n          go-version: '1.23'\n      \n      - name: Lint\n        uses: golangci/golangci-lint-action@v6\n        with:\n          version: latest\n      \n      - name: Test\n        run: go test -race -coverprofile=coverage.out ./...\n        env:\n          DATABASE_URL: postgres://postgres:test@localhost:5432/testdb?sslmode=disable\n      \n      - name: Coverage\n        run: |\n          COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}')\n          echo \"Coverage: $COVERAGE\"\n      \n      - name: Build\n        run: go build -o /dev/null ./...\n\nPhase 12: Performance Optimization\nPriority Stack\nPriority\tTechnique\tImpact\n1\tConnection pooling (pgx pool, HTTP client reuse)\t10-50x\n2\tAvoid unnecessary allocations (sync.Pool, pre-allocated slices)\t2-5x\n3\tUse strings.Builder for string concatenation\t5-20x\n4\tBatch database operations\t5-50x\n5\tCache hot paths (sync.Map, local cache, Redis)\t10-100x\n6\tProfile before optimizing (pprof)\t—\nProfiling\nimport _ \"net/http/pprof\"\n\n// In main.go (debug server on separate port)\ngo func() {\n    log.Println(http.ListenAndServe(\":6060\", nil))\n}()\n\n// Then: go tool pprof http://localhost:6060/debug/pprof/heap\n// Or:   go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30\n\nCommon Optimizations\n// ✅ Pre-allocate slices when length is known\nusers := make([]User, 0, len(ids))\n\n// ✅ strings.Builder for concatenation\nvar b strings.Builder\nb.Grow(estimatedLen)\nfor _, s := range parts {\n    b.WriteString(s)\n}\nresult := b.String()\n\n// ✅ Reuse HTTP clients (never create per-request)\nvar httpClient = &http.Client{\n    Timeout: 10 * time.Second,\n    Transport: &http.Transport{\n        MaxIdleConns:        100,\n        MaxIdleConnsPerHost: 10,\n        IdleConnTimeout:     90 * time.Second,\n    },\n}\n\n// ✅ sync.Pool for frequently allocated objects\nvar bufPool = sync.Pool{\n    New: func() any {\n        return new(bytes.Buffer)\n    },\n}\n\nfunc process() {\n    buf := bufPool.Get().(*bytes.Buffer)\n    defer func() {\n        buf.Reset()\n        bufPool.Put(buf)\n    }()\n    // use buf...\n}\n\nPhase 13: Security Hardening\nSecurity Checklist\nCategory\tCheck\tPriority\nInput\tValidate all input with validator/v10\tP0\nSQL\tUse parameterized queries (sqlc/pgx) — NEVER string concat\tP0\nAuth\tJWT validation with proper key rotation\tP0\nSecrets\tEnvironment variables only, never hardcoded\tP0\nDependencies\tgovulncheck in CI, go mod tidy regularly\tP1\nCORS\tStrict origin allowlist, not *\tP1\nRate limiting\tPer-IP and per-user limits\tP1\nHeaders\tSecurity headers middleware\tP1\nTLS\tTLS 1.2+ only, strong ciphers\tP1\nLogging\tNever log secrets, PII, or tokens\tP2\nSecurity Headers Middleware\nfunc SecurityHeaders(next http.Handler) http.Handler {\n    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        w.Header().Set(\"X-Content-Type-Options\", \"nosniff\")\n        w.Header().Set(\"X-Frame-Options\", \"DENY\")\n        w.Header().Set(\"X-XSS-Protection\", \"0\")\n        w.Header().Set(\"Strict-Transport-Security\", \"max-age=63072000; includeSubDomains\")\n        w.Header().Set(\"Content-Security-Policy\", \"default-src 'none'\")\n        w.Header().Set(\"Referrer-Policy\", \"strict-origin-when-cross-origin\")\n        next.ServeHTTP(w, r)\n    })\n}\n\nVulnerability Scanning\n# Install\ngo install golang.org/x/vuln/cmd/govulncheck@latest\n\n# Scan\ngovulncheck ./...\n\n# In CI — fail build on vulnerabilities\ngovulncheck -show verbose ./...\n\nPhase 14: Advanced Patterns\nGenerics (Go 1.18+)\n// Generic result type\ntype Result[T any] struct {\n    Data  T\n    Error error\n}\n\n// Generic repository\ntype Repository[T any] interface {\n    GetByID(ctx context.Context, id string) (*T, error)\n    List(ctx context.Context, filter Filter) ([]T, error)\n    Create(ctx context.Context, entity *T) error\n    Update(ctx context.Context, entity *T) error\n    Delete(ctx context.Context, id string) error\n}\n\n// Generic pagination\ntype Page[T any] struct {\n    Items      []T    `json:\"items\"`\n    NextCursor string `json:\"next_cursor,omitempty\"`\n    HasMore    bool   `json:\"has_more\"`\n}\n\nFunctional Options Pattern\ntype ServerOption func(*Server)\n\nfunc WithAddr(addr string) ServerOption {\n    return func(s *Server) { s.addr = addr }\n}\n\nfunc WithTimeout(d time.Duration) ServerOption {\n    return func(s *Server) { s.timeout = d }\n}\n\nfunc WithLogger(l *slog.Logger) ServerOption {\n    return func(s *Server) { s.logger = l }\n}\n\nfunc NewServer(opts ...ServerOption) *Server {\n    s := &Server{\n        addr:    \":8080\",\n        timeout: 30 * time.Second,\n        logger:  slog.Default(),\n    }\n    for _, opt := range opts {\n        opt(s)\n    }\n    return s\n}\n\nGraceful Degradation\n// Circuit breaker pattern (simplified)\ntype CircuitBreaker struct {\n    failures   atomic.Int64\n    threshold  int64\n    resetAfter time.Duration\n    lastFail   atomic.Int64\n}\n\nfunc (cb *CircuitBreaker) Execute(fn func() error) error {\n    if cb.isOpen() {\n        return ErrCircuitOpen\n    }\n    \n    err := fn()\n    if err != nil {\n        cb.failures.Add(1)\n        cb.lastFail.Store(time.Now().UnixNano())\n        return err\n    }\n    \n    cb.failures.Store(0)\n    return nil\n}\n\nfunc (cb *CircuitBreaker) isOpen() bool {\n    if cb.failures.Load() < cb.threshold {\n        return false\n    }\n    // Allow retry after reset period\n    elapsed := time.Since(time.Unix(0, cb.lastFail.Load()))\n    return elapsed < cb.resetAfter\n}\n\n10 Go Production Commandments\ninternal/ is the gatekeeper — hide implementation details aggressively\nErrors are values — wrap them, check them, never ignore them\n-race flag always — data races are silent killers\nInterfaces at the consumer — small, focused, implicit\nContext everywhere — first param for anything doing I/O\nerrgroup for goroutines — bounded concurrency, clean error handling\nsqlc over ORMs — type safety from actual SQL, zero runtime reflection\nProfile before optimizing — pprof doesn't lie, intuition does\nFail at startup — validate config, check connections, panic early\nGraceful shutdown — catch signals, drain connections, close cleanly\n10 Common Go Mistakes\nMistake\tImpact\tFix\nGoroutine leak\tMemory exhaustion\tAlways have termination path\nMissing error check\tSilent failures\terrcheck linter\nString concatenation in loop\tO(n²) allocations\tstrings.Builder\nCopy mutex\tSilent data race\tPass by pointer, embedder beware\nIgnoring context cancellation\tWasted resources\tCheck ctx.Err()\ninit() abuse\tHard to test, hidden side effects\tExplicit initialization\nInterface pollution\tOver-abstraction\tOnly abstract at consumption point\nMissing defer for cleanup\tResource leaks\tdefer immediately after acquire\nNil pointer on interface\tPanic at runtime\tCheck concrete value, not interface\ngo func() in loop (pre-1.22)\tWrong variable captured\titem := item or func param\nProduction Readiness Checklist\nMandatory (P0)\n -race clean test suite\n >80% test coverage on business logic\n Structured logging (slog/zerolog)\n Graceful shutdown with signal handling\n Health check endpoints (/healthz, /readyz)\n Configuration validation at startup\n Error wrapping with context throughout\n golangci-lint clean (strict config)\n Multi-stage Docker build (scratch/distroless)\n govulncheck clean\nRecommended (P1)\n OpenTelemetry tracing\n Prometheus metrics\n Request ID propagation\n Rate limiting\n Security headers\n Integration tests with testcontainers\n Database migrations (goose/migrate)\n CI/CD pipeline (lint → test → build → deploy)\nQuality Scoring (0-100)\nDimension\tWeight\tWhat to Evaluate\nError handling\t15%\tWrapping, sentinels, no swallowed errors\nConcurrency\t15%\tRace-free, context propagation, goroutine lifecycle\nTesting\t15%\tCoverage, table-driven, integration, -race\nCode organization\t15%\tPackage boundaries, internal/, dependency direction\nObservability\t10%\tStructured logging, metrics, tracing\nSecurity\t10%\tInput validation, govulncheck, secrets management\nPerformance\t10%\tProfiling, pooling, pre-allocation\nDocumentation\t10%\tGoDoc, README, ADRs\n\nGrade: 0-40 = 🔴 Needs rewrite | 41-60 = 🟡 Significant gaps | 61-80 = 🟢 Production ready | 81-100 = 💎 Exemplary\n\nNatural Language Commands\n\nWhen asked about Go projects, interpret these naturally:\n\n\"Review this Go code\" → Run quick health check, identify anti-patterns\n\"Set up a new Go service\" → Generate full project structure with all phases\n\"Fix the error handling\" → Apply Phase 2 patterns throughout\n\"Add tests\" → Generate table-driven tests following Phase 5\n\"Make this production ready\" → Run through production readiness checklist\n\"Profile this\" → Guide through pprof analysis\n\"Add observability\" → Apply Phase 10 (OTel + Prometheus)\n\"Optimize performance\" → Profile first, then apply Phase 12 priority stack\n\"Set up CI\" → Generate GitHub Actions + golangci-lint config\n\"Add database\" → pgx pool + sqlc + migration setup\n\"Review architecture\" → Evaluate against Phase 1 rules\n\"Security audit\" → Run through Phase 13 checklist"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/1kalin/afrexai-go-production",
    "publisherUrl": "https://clawhub.ai/1kalin/afrexai-go-production",
    "owner": "1kalin",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/afrexai-go-production",
    "downloadUrl": "https://openagent3.xyz/downloads/afrexai-go-production",
    "agentUrl": "https://openagent3.xyz/skills/afrexai-go-production/agent",
    "manifestUrl": "https://openagent3.xyz/skills/afrexai-go-production/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/afrexai-go-production/agent.md"
  }
}