[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6JD10A1G0GP7NPBQYGSGCQJ":3,"skill-same:01M6JD10A1G0GP7NPBQYGSGCQJ":55},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":27,"linkOnly":28,"markdownContent":29,"markdownBody":30,"frontMatter":31,"refName":33,"commitSha":34,"skillDirectory":35,"forksCount":36,"repositoryHtmlUrl":37,"repositoryHomepageUrl":38,"ownerHtmlUrl":39,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":40,"install":41,"resources":54},"01M6JD10A1G0GP7NPBQYGSGCQJ","golang-patterns",null,"Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.","S3YED\u002Fappie-kit","S3YED","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F62743867?v=4","01M6JBKBRRVP6KMS0VWZ27T3R6","01M6JBKBX0KG30284PW1DBYJT1",14,"MIT","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fecc\u002Fgolang-patterns\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26],"golang","golang patterns","patterns","go","best practices","applications","conventions","for","idiomatic","2026-11-10 10:12:30",false,"---\nname: golang-patterns\ndescription: Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.\norigin: ECC\n---\n\n# Go Development Patterns\n\nIdiomatic Go patterns and best practices for building robust, efficient, and maintainable applications.\n\n## When to Activate\n\n- Writing new Go code\n- Reviewing Go code\n- Refactoring existing Go code\n- Designing Go packages\u002Fmodules\n\n## Core Principles\n\n### 1. Simplicity and Clarity\n\nGo favors simplicity over cleverness. Code should be obvious and easy to read.\n\n```go\n\u002F\u002F Good: Clear and direct\nfunc GetUser(id string) (*User, error) {\n    user, err := db.FindUser(id)\n    if err != nil {\n        return nil, fmt.Errorf(\"get user %s: %w\", id, err)\n    }\n    return user, nil\n}\n\n\u002F\u002F Bad: Overly clever\nfunc GetUser(id string) (*User, error) {\n    return func() (*User, error) {\n        if u, e := db.FindUser(id); e == nil {\n            return u, nil\n        } else {\n            return nil, e\n        }\n    }()\n}\n```\n\n### 2. Make the Zero Value Useful\n\nDesign types so their zero value is immediately usable without initialization.\n\n```go\n\u002F\u002F Good: Zero value is useful\ntype Counter struct {\n    mu    sync.Mutex\n    count int \u002F\u002F zero value is 0, ready to use\n}\n\nfunc (c *Counter) Inc() {\n    c.mu.Lock()\n    c.count++\n    c.mu.Unlock()\n}\n\n\u002F\u002F Good: bytes.Buffer works with zero value\nvar buf bytes.Buffer\nbuf.WriteString(\"hello\")\n\n\u002F\u002F Bad: Requires initialization\ntype BadCounter struct {\n    counts map[string]int \u002F\u002F nil map will panic\n}\n```\n\n### 3. Accept Interfaces, Return Structs\n\nFunctions should accept interface parameters and return concrete types.\n\n```go\n\u002F\u002F Good: Accepts interface, returns concrete type\nfunc ProcessData(r io.Reader) (*Result, error) {\n    data, err := io.ReadAll(r)\n    if err != nil {\n        return nil, err\n    }\n    return &Result{Data: data}, nil\n}\n\n\u002F\u002F Bad: Returns interface (hides implementation details unnecessarily)\nfunc ProcessData(r io.Reader) (io.Reader, error) {\n    \u002F\u002F ...\n}\n```\n\n## Error Handling Patterns\n\n### Error Wrapping with Context\n\n```go\n\u002F\u002F Good: Wrap errors with context\nfunc LoadConfig(path string) (*Config, error) {\n    data, err := os.ReadFile(path)\n    if err != nil {\n        return nil, fmt.Errorf(\"load config %s: %w\", path, err)\n    }\n\n    var cfg Config\n    if err := json.Unmarshal(data, &cfg); err != nil {\n        return nil, fmt.Errorf(\"parse config %s: %w\", path, err)\n    }\n\n    return &cfg, nil\n}\n```\n\n### Custom Error Types\n\n```go\n\u002F\u002F Define domain-specific errors\ntype ValidationError struct {\n    Field   string\n    Message string\n}\n\nfunc (e *ValidationError) Error() string {\n    return fmt.Sprintf(\"validation failed on %s: %s\", e.Field, e.Message)\n}\n\n\u002F\u002F Sentinel errors for common cases\nvar (\n    ErrNotFound     = errors.New(\"resource not found\")\n    ErrUnauthorized = errors.New(\"unauthorized\")\n    ErrInvalidInput = errors.New(\"invalid input\")\n)\n```\n\n### Error Checking with errors.Is and errors.As\n\n```go\nfunc HandleError(err error) {\n    \u002F\u002F Check for specific error\n    if errors.Is(err, sql.ErrNoRows) {\n        log.Println(\"No records found\")\n        return\n    }\n\n    \u002F\u002F Check for error type\n    var validationErr *ValidationError\n    if errors.As(err, &validationErr) {\n        log.Printf(\"Validation error on field %s: %s\",\n            validationErr.Field, validationErr.Message)\n        return\n    }\n\n    \u002F\u002F Unknown error\n    log.Printf(\"Unexpected error: %v\", err)\n}\n```\n\n### Never Ignore Errors\n\n```go\n\u002F\u002F Bad: Ignoring error with blank identifier\nresult, _ := doSomething()\n\n\u002F\u002F Good: Handle or explicitly document why it's safe to ignore\nresult, err := doSomething()\nif err != nil {\n    return err\n}\n\n\u002F\u002F Acceptable: When error truly doesn't matter (rare)\n_ = writer.Close() \u002F\u002F Best-effort cleanup, error logged elsewhere\n```\n\n## Concurrency Patterns\n\n### Worker Pool\n\n```go\nfunc WorkerPool(jobs \u003C-chan Job, results chan\u003C- Result, numWorkers int) {\n    var wg sync.WaitGroup\n\n    for i := 0; i \u003C numWorkers; i++ {\n        wg.Add(1)\n        go func() {\n            defer wg.Done()\n            for job := range jobs {\n                results \u003C- process(job)\n            }\n        }()\n    }\n\n    wg.Wait()\n    close(results)\n}\n```\n\n### Context for Cancellation and Timeouts\n\n```go\nfunc FetchWithTimeout(ctx context.Context, url string) ([]byte, error) {\n    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)\n    defer cancel()\n\n    req, err := http.NewRequestWithContext(ctx, \"GET\", url, nil)\n    if err != nil {\n        return nil, fmt.Errorf(\"create request: %w\", err)\n    }\n\n    resp, err := http.DefaultClient.Do(req)\n    if err != nil {\n        return nil, fmt.Errorf(\"fetch %s: %w\", url, err)\n    }\n    defer resp.Body.Close()\n\n    return io.ReadAll(resp.Body)\n}\n```\n\n### Graceful Shutdown\n\n```go\nfunc GracefulShutdown(server *http.Server) {\n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n\n    \u003C-quit\n    log.Println(\"Shutting down server...\")\n\n    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n    defer cancel()\n\n    if err := server.Shutdown(ctx); err != nil {\n        log.Fatalf(\"Server forced to shutdown: %v\", err)\n    }\n\n    log.Println(\"Server exited\")\n}\n```\n\n### errgroup for Coordinated Goroutines\n\n```go\nimport \"golang.org\u002Fx\u002Fsync\u002Ferrgroup\"\n\nfunc FetchAll(ctx context.Context, urls []string) ([][]byte, error) {\n    g, ctx := errgroup.WithContext(ctx)\n    results := make([][]byte, len(urls))\n\n    for i, url := range urls {\n        i, url := i, url \u002F\u002F Capture loop variables\n        g.Go(func() error {\n            data, err := FetchWithTimeout(ctx, url)\n            if err != nil {\n                return err\n            }\n            results[i] = data\n            return nil\n        })\n    }\n\n    if err := g.Wait(); err != nil {\n        return nil, err\n    }\n    return results, nil\n}\n```\n\n### Avoiding Goroutine Leaks\n\n```go\n\u002F\u002F Bad: Goroutine leak if context is cancelled\nfunc leakyFetch(ctx context.Context, url string) \u003C-chan []byte {\n    ch := make(chan []byte)\n    go func() {\n        data, _ := fetch(url)\n        ch \u003C- data \u002F\u002F Blocks forever if no receiver\n    }()\n    return ch\n}\n\n\u002F\u002F Good: Properly handles cancellation\nfunc safeFetch(ctx context.Context, url string) \u003C-chan []byte {\n    ch := make(chan []byte, 1) \u002F\u002F Buffered channel\n    go func() {\n        data, err := fetch(url)\n        if err != nil {\n            return\n        }\n        select {\n        case ch \u003C- data:\n        case \u003C-ctx.Done():\n        }\n    }()\n    return ch\n}\n```\n\n## Interface Design\n\n### Small, Focused Interfaces\n\n```go\n\u002F\u002F Good: Single-method interfaces\ntype Reader interface {\n    Read(p []byte) (n int, err error)\n}\n\ntype Writer interface {\n    Write(p []byte) (n int, err error)\n}\n\ntype Closer interface {\n    Close() error\n}\n\n\u002F\u002F Compose interfaces as needed\ntype ReadWriteCloser interface {\n    Reader\n    Writer\n    Closer\n}\n```\n\n### Define Interfaces Where They're Used\n\n```go\n\u002F\u002F In the consumer package, not the provider\npackage service\n\n\u002F\u002F UserStore defines what this service needs\ntype UserStore interface {\n    GetUser(id string) (*User, error)\n    SaveUser(user *User) error\n}\n\ntype Service struct {\n    store UserStore\n}\n\n\u002F\u002F Concrete implementation can be in another package\n\u002F\u002F It doesn't need to know about this interface\n```\n\n### Optional Behavior with Type Assertions\n\n```go\ntype Flusher interface {\n    Flush() error\n}\n\nfunc WriteAndFlush(w io.Writer, data []byte) error {\n    if _, err := w.Write(data); err != nil {\n        return err\n    }\n\n    \u002F\u002F Flush if supported\n    if f, ok := w.(Flusher); ok {\n        return f.Flush()\n    }\n    return nil\n}\n```\n\n## Package Organization\n\n### Standard Project Layout\n\n```text\nmyproject\u002F\n├── cmd\u002F\n│   └── myapp\u002F\n│       └── main.go           # Entry point\n├── internal\u002F\n│   ├── handler\u002F              # HTTP handlers\n│   ├── service\u002F              # Business logic\n│   ├── repository\u002F           # Data access\n│   └── config\u002F               # Configuration\n├── pkg\u002F\n│   └── client\u002F               # Public API client\n├── api\u002F\n│   └── v1\u002F                   # API definitions (proto, OpenAPI)\n├── testdata\u002F                 # Test fixtures\n├── go.mod\n├── go.sum\n└── Makefile\n```\n\n### Package Naming\n\n```go\n\u002F\u002F Good: Short, lowercase, no underscores\npackage http\npackage json\npackage user\n\n\u002F\u002F Bad: Verbose, mixed case, or redundant\npackage httpHandler\npackage json_parser\npackage userService \u002F\u002F Redundant 'Service' suffix\n```\n\n### Avoid Package-Level State\n\n```go\n\u002F\u002F Bad: Global mutable state\nvar db *sql.DB\n\nfunc init() {\n    db, _ = sql.Open(\"postgres\", os.Getenv(\"DATABASE_URL\"))\n}\n\n\u002F\u002F Good: Dependency injection\ntype Server struct {\n    db *sql.DB\n}\n\nfunc NewServer(db *sql.DB) *Server {\n    return &Server{db: db}\n}\n```\n\n## Struct Design\n\n### Functional Options Pattern\n\n```go\ntype Server struct {\n    addr    string\n    timeout time.Duration\n    logger  *log.Logger\n}\n\ntype Option func(*Server)\n\nfunc WithTimeout(d time.Duration) Option {\n    return func(s *Server) {\n        s.timeout = d\n    }\n}\n\nfunc WithLogger(l *log.Logger) Option {\n    return func(s *Server) {\n        s.logger = l\n    }\n}\n\nfunc NewServer(addr string, opts ...Option) *Server {\n    s := &Server{\n        addr:    addr,\n        timeout: 30 * time.Second, \u002F\u002F default\n        logger:  log.Default(),    \u002F\u002F default\n    }\n    for _, opt := range opts {\n        opt(s)\n    }\n    return s\n}\n\n\u002F\u002F Usage\nserver := NewServer(\":8080\",\n    WithTimeout(60*time.Second),\n    WithLogger(customLogger),\n)\n```\n\n### Embedding for Composition\n\n```go\ntype Logger struct {\n    prefix string\n}\n\nfunc (l *Logger) Log(msg string) {\n    fmt.Printf(\"[%s] %s\\n\", l.prefix, msg)\n}\n\ntype Server struct {\n    *Logger \u002F\u002F Embedding - Server gets Log method\n    addr    string\n}\n\nfunc NewServer(addr string) *Server {\n    return &Server{\n        Logger: &Logger{prefix: \"SERVER\"},\n        addr:   addr,\n    }\n}\n\n\u002F\u002F Usage\ns := NewServer(\":8080\")\ns.Log(\"Starting...\") \u002F\u002F Calls embedded Logger.Log\n```\n\n## Memory and Performance\n\n### Preallocate Slices When Size is Known\n\n```go\n\u002F\u002F Bad: Grows slice multiple times\nfunc processItems(items []Item) []Result {\n    var results []Result\n    for _, item := range items {\n        results = append(results, process(item))\n    }\n    return results\n}\n\n\u002F\u002F Good: Single allocation\nfunc processItems(items []Item) []Result {\n    results := make([]Result, 0, len(items))\n    for _, item := range items {\n        results = append(results, process(item))\n    }\n    return results\n}\n```\n\n### Use sync.Pool for Frequent Allocations\n\n```go\nvar bufferPool = sync.Pool{\n    New: func() interface{} {\n        return new(bytes.Buffer)\n    },\n}\n\nfunc ProcessRequest(data []byte) []byte {\n    buf := bufferPool.Get().(*bytes.Buffer)\n    defer func() {\n        buf.Reset()\n        bufferPool.Put(buf)\n    }()\n\n    buf.Write(data)\n    \u002F\u002F Process...\n    return buf.Bytes()\n}\n```\n\n### Avoid String Concatenation in Loops\n\n```go\n\u002F\u002F Bad: Creates many string allocations\nfunc join(parts []string) string {\n    var result string\n    for _, p := range parts {\n        result += p + \",\"\n    }\n    return result\n}\n\n\u002F\u002F Good: Single allocation with strings.Builder\nfunc join(parts []string) string {\n    var sb strings.Builder\n    for i, p := range parts {\n        if i > 0 {\n            sb.WriteString(\",\")\n        }\n        sb.WriteString(p)\n    }\n    return sb.String()\n}\n\n\u002F\u002F Best: Use standard library\nfunc join(parts []string) string {\n    return strings.Join(parts, \",\")\n}\n```\n\n## Go Tooling Integration\n\n### Essential Commands\n\n```bash\n# Build and run\ngo build .\u002F...\ngo run .\u002Fcmd\u002Fmyapp\n\n# Testing\ngo test .\u002F...\ngo test -race .\u002F...\ngo test -cover .\u002F...\n\n# Static analysis\ngo vet .\u002F...\nstaticcheck .\u002F...\ngolangci-lint run\n\n# Module management\ngo mod tidy\ngo mod verify\n\n# Formatting\ngofmt -w .\ngoimports -w .\n```\n\n### Recommended Linter Configuration (.golangci.yml)\n\n```yaml\nlinters:\n  enable:\n    - errcheck\n    - gosimple\n    - govet\n    - ineffassign\n    - staticcheck\n    - unused\n    - gofmt\n    - goimports\n    - misspell\n    - unconvert\n    - unparam\n\nlinters-settings:\n  errcheck:\n    check-type-assertions: true\n  govet:\n    check-shadowing: true\n\nissues:\n  exclude-use-default: false\n```\n\n## Quick Reference: Go Idioms\n\n| Idiom | Description |\n|-------|-------------|\n| Accept interfaces, return structs | Functions accept interface params, return concrete types |\n| Errors are values | Treat errors as first-class values, not exceptions |\n| Don't communicate by sharing memory | Use channels for coordination between goroutines |\n| Make the zero value useful | Types should work without explicit initialization |\n| A little copying is better than a little dependency | Avoid unnecessary external dependencies |\n| Clear is better than clever | Prioritize readability over cleverness |\n| gofmt is no one's favorite but everyone's friend | Always format with gofmt\u002Fgoimports |\n| Return early | Handle errors first, keep happy path unindented |\n\n## Anti-Patterns to Avoid\n\n```go\n\u002F\u002F Bad: Naked returns in long functions\nfunc process() (result int, err error) {\n    \u002F\u002F ... 50 lines ...\n    return \u002F\u002F What is being returned?\n}\n\n\u002F\u002F Bad: Using panic for control flow\nfunc GetUser(id string) *User {\n    user, err := db.Find(id)\n    if err != nil {\n        panic(err) \u002F\u002F Don't do this\n    }\n    return user\n}\n\n\u002F\u002F Bad: Passing context in struct\ntype Request struct {\n    ctx context.Context \u002F\u002F Context should be first param\n    ID  string\n}\n\n\u002F\u002F Good: Context as first parameter\nfunc ProcessRequest(ctx context.Context, id string) error {\n    \u002F\u002F ...\n}\n\n\u002F\u002F Bad: Mixing value and pointer receivers\ntype Counter struct{ n int }\nfunc (c Counter) Value() int { return c.n }    \u002F\u002F Value receiver\nfunc (c *Counter) Increment() { c.n++ }        \u002F\u002F Pointer receiver\n\u002F\u002F Pick one style and be consistent\n```\n\n**Remember**: Go code should be boring in the best way - predictable, consistent, and easy to understand. When in doubt, keep it simple.\n","# Go Development Patterns\n\nIdiomatic Go patterns and best practices for building robust, efficient, and maintainable applications.\n\n## When to Activate\n\n- Writing new Go code\n- Reviewing Go code\n- Refactoring existing Go code\n- Designing Go packages\u002Fmodules\n\n## Core Principles\n\n### 1. Simplicity and Clarity\n\nGo favors simplicity over cleverness. Code should be obvious and easy to read.\n\n```go\n\u002F\u002F Good: Clear and direct\nfunc GetUser(id string) (*User, error) {\n    user, err := db.FindUser(id)\n    if err != nil {\n        return nil, fmt.Errorf(\"get user %s: %w\", id, err)\n    }\n    return user, nil\n}\n\n\u002F\u002F Bad: Overly clever\nfunc GetUser(id string) (*User, error) {\n    return func() (*User, error) {\n        if u, e := db.FindUser(id); e == nil {\n            return u, nil\n        } else {\n            return nil, e\n        }\n    }()\n}\n```\n\n### 2. Make the Zero Value Useful\n\nDesign types so their zero value is immediately usable without initialization.\n\n```go\n\u002F\u002F Good: Zero value is useful\ntype Counter struct {\n    mu    sync.Mutex\n    count int \u002F\u002F zero value is 0, ready to use\n}\n\nfunc (c *Counter) Inc() {\n    c.mu.Lock()\n    c.count++\n    c.mu.Unlock()\n}\n\n\u002F\u002F Good: bytes.Buffer works with zero value\nvar buf bytes.Buffer\nbuf.WriteString(\"hello\")\n\n\u002F\u002F Bad: Requires initialization\ntype BadCounter struct {\n    counts map[string]int \u002F\u002F nil map will panic\n}\n```\n\n### 3. Accept Interfaces, Return Structs\n\nFunctions should accept interface parameters and return concrete types.\n\n```go\n\u002F\u002F Good: Accepts interface, returns concrete type\nfunc ProcessData(r io.Reader) (*Result, error) {\n    data, err := io.ReadAll(r)\n    if err != nil {\n        return nil, err\n    }\n    return &Result{Data: data}, nil\n}\n\n\u002F\u002F Bad: Returns interface (hides implementation details unnecessarily)\nfunc ProcessData(r io.Reader) (io.Reader, error) {\n    \u002F\u002F ...\n}\n```\n\n## Error Handling Patterns\n\n### Error Wrapping with Context\n\n```go\n\u002F\u002F Good: Wrap errors with context\nfunc LoadConfig(path string) (*Config, error) {\n    data, err := os.ReadFile(path)\n    if err != nil {\n        return nil, fmt.Errorf(\"load config %s: %w\", path, err)\n    }\n\n    var cfg Config\n    if err := json.Unmarshal(data, &cfg); err != nil {\n        return nil, fmt.Errorf(\"parse config %s: %w\", path, err)\n    }\n\n    return &cfg, nil\n}\n```\n\n### Custom Error Types\n\n```go\n\u002F\u002F Define domain-specific errors\ntype ValidationError struct {\n    Field   string\n    Message string\n}\n\nfunc (e *ValidationError) Error() string {\n    return fmt.Sprintf(\"validation failed on %s: %s\", e.Field, e.Message)\n}\n\n\u002F\u002F Sentinel errors for common cases\nvar (\n    ErrNotFound     = errors.New(\"resource not found\")\n    ErrUnauthorized = errors.New(\"unauthorized\")\n    ErrInvalidInput = errors.New(\"invalid input\")\n)\n```\n\n### Error Checking with errors.Is and errors.As\n\n```go\nfunc HandleError(err error) {\n    \u002F\u002F Check for specific error\n    if errors.Is(err, sql.ErrNoRows) {\n        log.Println(\"No records found\")\n        return\n    }\n\n    \u002F\u002F Check for error type\n    var validationErr *ValidationError\n    if errors.As(err, &validationErr) {\n        log.Printf(\"Validation error on field %s: %s\",\n            validationErr.Field, validationErr.Message)\n        return\n    }\n\n    \u002F\u002F Unknown error\n    log.Printf(\"Unexpected error: %v\", err)\n}\n```\n\n### Never Ignore Errors\n\n```go\n\u002F\u002F Bad: Ignoring error with blank identifier\nresult, _ := doSomething()\n\n\u002F\u002F Good: Handle or explicitly document why it's safe to ignore\nresult, err := doSomething()\nif err != nil {\n    return err\n}\n\n\u002F\u002F Acceptable: When error truly doesn't matter (rare)\n_ = writer.Close() \u002F\u002F Best-effort cleanup, error logged elsewhere\n```\n\n## Concurrency Patterns\n\n### Worker Pool\n\n```go\nfunc WorkerPool(jobs \u003C-chan Job, results chan\u003C- Result, numWorkers int) {\n    var wg sync.WaitGroup\n\n    for i := 0; i \u003C numWorkers; i++ {\n        wg.Add(1)\n        go func() {\n            defer wg.Done()\n            for job := range jobs {\n                results \u003C- process(job)\n            }\n        }()\n    }\n\n    wg.Wait()\n    close(results)\n}\n```\n\n### Context for Cancellation and Timeouts\n\n```go\nfunc FetchWithTimeout(ctx context.Context, url string) ([]byte, error) {\n    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)\n    defer cancel()\n\n    req, err := http.NewRequestWithContext(ctx, \"GET\", url, nil)\n    if err != nil {\n        return nil, fmt.Errorf(\"create request: %w\", err)\n    }\n\n    resp, err := http.DefaultClient.Do(req)\n    if err != nil {\n        return nil, fmt.Errorf(\"fetch %s: %w\", url, err)\n    }\n    defer resp.Body.Close()\n\n    return io.ReadAll(resp.Body)\n}\n```\n\n### Graceful Shutdown\n\n```go\nfunc GracefulShutdown(server *http.Server) {\n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n\n    \u003C-quit\n    log.Println(\"Shutting down server...\")\n\n    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n    defer cancel()\n\n    if err := server.Shutdown(ctx); err != nil {\n        log.Fatalf(\"Server forced to shutdown: %v\", err)\n    }\n\n    log.Println(\"Server exited\")\n}\n```\n\n### errgroup for Coordinated Goroutines\n\n```go\nimport \"golang.org\u002Fx\u002Fsync\u002Ferrgroup\"\n\nfunc FetchAll(ctx context.Context, urls []string) ([][]byte, error) {\n    g, ctx := errgroup.WithContext(ctx)\n    results := make([][]byte, len(urls))\n\n    for i, url := range urls {\n        i, url := i, url \u002F\u002F Capture loop variables\n        g.Go(func() error {\n            data, err := FetchWithTimeout(ctx, url)\n            if err != nil {\n                return err\n            }\n            results[i] = data\n            return nil\n        })\n    }\n\n    if err := g.Wait(); err != nil {\n        return nil, err\n    }\n    return results, nil\n}\n```\n\n### Avoiding Goroutine Leaks\n\n```go\n\u002F\u002F Bad: Goroutine leak if context is cancelled\nfunc leakyFetch(ctx context.Context, url string) \u003C-chan []byte {\n    ch := make(chan []byte)\n    go func() {\n        data, _ := fetch(url)\n        ch \u003C- data \u002F\u002F Blocks forever if no receiver\n    }()\n    return ch\n}\n\n\u002F\u002F Good: Properly handles cancellation\nfunc safeFetch(ctx context.Context, url string) \u003C-chan []byte {\n    ch := make(chan []byte, 1) \u002F\u002F Buffered channel\n    go func() {\n        data, err := fetch(url)\n        if err != nil {\n            return\n        }\n        select {\n        case ch \u003C- data:\n        case \u003C-ctx.Done():\n        }\n    }()\n    return ch\n}\n```\n\n## Interface Design\n\n### Small, Focused Interfaces\n\n```go\n\u002F\u002F Good: Single-method interfaces\ntype Reader interface {\n    Read(p []byte) (n int, err error)\n}\n\ntype Writer interface {\n    Write(p []byte) (n int, err error)\n}\n\ntype Closer interface {\n    Close() error\n}\n\n\u002F\u002F Compose interfaces as needed\ntype ReadWriteCloser interface {\n    Reader\n    Writer\n    Closer\n}\n```\n\n### Define Interfaces Where They're Used\n\n```go\n\u002F\u002F In the consumer package, not the provider\npackage service\n\n\u002F\u002F UserStore defines what this service needs\ntype UserStore interface {\n    GetUser(id string) (*User, error)\n    SaveUser(user *User) error\n}\n\ntype Service struct {\n    store UserStore\n}\n\n\u002F\u002F Concrete implementation can be in another package\n\u002F\u002F It doesn't need to know about this interface\n```\n\n### Optional Behavior with Type Assertions\n\n```go\ntype Flusher interface {\n    Flush() error\n}\n\nfunc WriteAndFlush(w io.Writer, data []byte) error {\n    if _, err := w.Write(data); err != nil {\n        return err\n    }\n\n    \u002F\u002F Flush if supported\n    if f, ok := w.(Flusher); ok {\n        return f.Flush()\n    }\n    return nil\n}\n```\n\n## Package Organization\n\n### Standard Project Layout\n\n```text\nmyproject\u002F\n├── cmd\u002F\n│   └── myapp\u002F\n│       └── main.go           # Entry point\n├── internal\u002F\n│   ├── handler\u002F              # HTTP handlers\n│   ├── service\u002F              # Business logic\n│   ├── repository\u002F           # Data access\n│   └── config\u002F               # Configuration\n├── pkg\u002F\n│   └── client\u002F               # Public API client\n├── api\u002F\n│   └── v1\u002F                   # API definitions (proto, OpenAPI)\n├── testdata\u002F                 # Test fixtures\n├── go.mod\n├── go.sum\n└── Makefile\n```\n\n### Package Naming\n\n```go\n\u002F\u002F Good: Short, lowercase, no underscores\npackage http\npackage json\npackage user\n\n\u002F\u002F Bad: Verbose, mixed case, or redundant\npackage httpHandler\npackage json_parser\npackage userService \u002F\u002F Redundant 'Service' suffix\n```\n\n### Avoid Package-Level State\n\n```go\n\u002F\u002F Bad: Global mutable state\nvar db *sql.DB\n\nfunc init() {\n    db, _ = sql.Open(\"postgres\", os.Getenv(\"DATABASE_URL\"))\n}\n\n\u002F\u002F Good: Dependency injection\ntype Server struct {\n    db *sql.DB\n}\n\nfunc NewServer(db *sql.DB) *Server {\n    return &Server{db: db}\n}\n```\n\n## Struct Design\n\n### Functional Options Pattern\n\n```go\ntype Server struct {\n    addr    string\n    timeout time.Duration\n    logger  *log.Logger\n}\n\ntype Option func(*Server)\n\nfunc WithTimeout(d time.Duration) Option {\n    return func(s *Server) {\n        s.timeout = d\n    }\n}\n\nfunc WithLogger(l *log.Logger) Option {\n    return func(s *Server) {\n        s.logger = l\n    }\n}\n\nfunc NewServer(addr string, opts ...Option) *Server {\n    s := &Server{\n        addr:    addr,\n        timeout: 30 * time.Second, \u002F\u002F default\n        logger:  log.Default(),    \u002F\u002F default\n    }\n    for _, opt := range opts {\n        opt(s)\n    }\n    return s\n}\n\n\u002F\u002F Usage\nserver := NewServer(\":8080\",\n    WithTimeout(60*time.Second),\n    WithLogger(customLogger),\n)\n```\n\n### Embedding for Composition\n\n```go\ntype Logger struct {\n    prefix string\n}\n\nfunc (l *Logger) Log(msg string) {\n    fmt.Printf(\"[%s] %s\\n\", l.prefix, msg)\n}\n\ntype Server struct {\n    *Logger \u002F\u002F Embedding - Server gets Log method\n    addr    string\n}\n\nfunc NewServer(addr string) *Server {\n    return &Server{\n        Logger: &Logger{prefix: \"SERVER\"},\n        addr:   addr,\n    }\n}\n\n\u002F\u002F Usage\ns := NewServer(\":8080\")\ns.Log(\"Starting...\") \u002F\u002F Calls embedded Logger.Log\n```\n\n## Memory and Performance\n\n### Preallocate Slices When Size is Known\n\n```go\n\u002F\u002F Bad: Grows slice multiple times\nfunc processItems(items []Item) []Result {\n    var results []Result\n    for _, item := range items {\n        results = append(results, process(item))\n    }\n    return results\n}\n\n\u002F\u002F Good: Single allocation\nfunc processItems(items []Item) []Result {\n    results := make([]Result, 0, len(items))\n    for _, item := range items {\n        results = append(results, process(item))\n    }\n    return results\n}\n```\n\n### Use sync.Pool for Frequent Allocations\n\n```go\nvar bufferPool = sync.Pool{\n    New: func() interface{} {\n        return new(bytes.Buffer)\n    },\n}\n\nfunc ProcessRequest(data []byte) []byte {\n    buf := bufferPool.Get().(*bytes.Buffer)\n    defer func() {\n        buf.Reset()\n        bufferPool.Put(buf)\n    }()\n\n    buf.Write(data)\n    \u002F\u002F Process...\n    return buf.Bytes()\n}\n```\n\n### Avoid String Concatenation in Loops\n\n```go\n\u002F\u002F Bad: Creates many string allocations\nfunc join(parts []string) string {\n    var result string\n    for _, p := range parts {\n        result += p + \",\"\n    }\n    return result\n}\n\n\u002F\u002F Good: Single allocation with strings.Builder\nfunc join(parts []string) string {\n    var sb strings.Builder\n    for i, p := range parts {\n        if i > 0 {\n            sb.WriteString(\",\")\n        }\n        sb.WriteString(p)\n    }\n    return sb.String()\n}\n\n\u002F\u002F Best: Use standard library\nfunc join(parts []string) string {\n    return strings.Join(parts, \",\")\n}\n```\n\n## Go Tooling Integration\n\n### Essential Commands\n\n```bash\n# Build and run\ngo build .\u002F...\ngo run .\u002Fcmd\u002Fmyapp\n\n# Testing\ngo test .\u002F...\ngo test -race .\u002F...\ngo test -cover .\u002F...\n\n# Static analysis\ngo vet .\u002F...\nstaticcheck .\u002F...\ngolangci-lint run\n\n# Module management\ngo mod tidy\ngo mod verify\n\n# Formatting\ngofmt -w .\ngoimports -w .\n```\n\n### Recommended Linter Configuration (.golangci.yml)\n\n```yaml\nlinters:\n  enable:\n    - errcheck\n    - gosimple\n    - govet\n    - ineffassign\n    - staticcheck\n    - unused\n    - gofmt\n    - goimports\n    - misspell\n    - unconvert\n    - unparam\n\nlinters-settings:\n  errcheck:\n    check-type-assertions: true\n  govet:\n    check-shadowing: true\n\nissues:\n  exclude-use-default: false\n```\n\n## Quick Reference: Go Idioms\n\n| Idiom | Description |\n|-------|-------------|\n| Accept interfaces, return structs | Functions accept interface params, return concrete types |\n| Errors are values | Treat errors as first-class values, not exceptions |\n| Don't communicate by sharing memory | Use channels for coordination between goroutines |\n| Make the zero value useful | Types should work without explicit initialization |\n| A little copying is better than a little dependency | Avoid unnecessary external dependencies |\n| Clear is better than clever | Prioritize readability over cleverness |\n| gofmt is no one's favorite but everyone's friend | Always format with gofmt\u002Fgoimports |\n| Return early | Handle errors first, keep happy path unindented |\n\n## Anti-Patterns to Avoid\n\n```go\n\u002F\u002F Bad: Naked returns in long functions\nfunc process() (result int, err error) {\n    \u002F\u002F ... 50 lines ...\n    return \u002F\u002F What is being returned?\n}\n\n\u002F\u002F Bad: Using panic for control flow\nfunc GetUser(id string) *User {\n    user, err := db.Find(id)\n    if err != nil {\n        panic(err) \u002F\u002F Don't do this\n    }\n    return user\n}\n\n\u002F\u002F Bad: Passing context in struct\ntype Request struct {\n    ctx context.Context \u002F\u002F Context should be first param\n    ID  string\n}\n\n\u002F\u002F Good: Context as first parameter\nfunc ProcessRequest(ctx context.Context, id string) error {\n    \u002F\u002F ...\n}\n\n\u002F\u002F Bad: Mixing value and pointer receivers\ntype Counter struct{ n int }\nfunc (c Counter) Value() int { return c.n }    \u002F\u002F Value receiver\nfunc (c *Counter) Increment() { c.n++ }        \u002F\u002F Pointer receiver\n\u002F\u002F Pick one style and be consistent\n```\n\n**Remember**: Go code should be boring in the best way - predictable, consistent, and easy to understand. When in doubt, keep it simple.\n",{"name":5,"origin":32,"description":7},"ECC","master","8ec37df6d71fb664ea19d32c079e7d3ff931a8e0","skills\u002Fecc\u002Fgolang-patterns",3,"https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit","https:\u002F\u002Fweblyfe.ai","https:\u002F\u002Fgithub.com\u002FS3YED","2026-08-27 01:54:02",{"source":8,"skillName":5,"commands":42,"prompt":52,"zipAvailable":53},[43,46,49],{"tool":44,"command":45},"npx","npx skills add S3YED\u002Fappie-kit --skill golang-patterns",{"tool":47,"command":48},"bunx","bunx skills add S3YED\u002Fappie-kit --skill golang-patterns",{"tool":50,"command":51},"pnpm","pnpm dlx skills add S3YED\u002Fappie-kit --skill golang-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fecc\u002Fgolang-patterns\u002FSKILL.md",true,[],[56,92,127,153,184,208],{"skillNo":57,"name":58,"nameZh":6,"description":59,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":60,"categories":61,"keywords":73,"publishedAt":27},"01M6JFD4M6N4DSGC7TXEJ5R3J2","ai-music","AI music generation and audio tools: HeartMuLa lyrics-to-music generation, songwriting craft (+ Suno prompts), and audio spectrogram\u002Ffeature visualization.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fwethlete\u002Fai-music\u002FSKILL.md",[62,67,70],{"categoryNo":63,"categoryName":64,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000013","分析与可视化","SCENARIO","使用场景",{"categoryNo":68,"categoryName":69,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":71,"categoryName":72,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000023","Skill与智能体开发",[74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91],"music","ai music","humanizer","visualization","Tools","Audio","hermes","hermes agent","songwriting","suno","lyrics","prompts","heartmula","craft","generation","feature","ai music generation","music generation",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":106,"publishedAt":27},"01M6JFCZE4XNFQFMNZDHKHT5V5","agentic-webdesign-design-system-ingestion","Use v0 Design Systems 2.0, Bolt Design System Agents, or Lovable to generate production UI from a client's real design system components — not generic Tailwind. Use when building a client website where brand consistency matters.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fweb-design\u002Fagentic-webdesign-design-system-ingestion\u002FSKILL.md",[98,101],{"categoryNo":99,"categoryName":100,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":102,"categoryName":103,"taxonomyType":104,"taxonomyTypeDesc":105},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126],"design","agentic","design system","system","ingestion","webdesign","agentic webdesign design system ingestion","components","generate","design systems","website","ui","Tailwind","bolt","lovable","v0","design-system","wed","design system components","appie",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":135,"publishedAt":27},"01M6JFCVPX3913CFAS6QQJ33ZB","agentic-webdesign-agent-elements","Use 21st.dev Agent Elements — 25 shadcn\u002Fui components purpose-built for AI agent UIs. Tool cards (Bash, Edit, Search, Plan, Subagent, MCP), chat, input, streaming. Open source, shadcn-registry install, no runtime lock-in.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fweb-design\u002Fagentic-webdesign-agent-elements\u002FSKILL.md",[133,134],{"categoryNo":71,"categoryName":72,"taxonomyType":65,"taxonomyTypeDesc":66},{"categoryNo":102,"categoryName":103,"taxonomyType":104,"taxonomyTypeDesc":105},[108,136,112,137,138,139,114,140,141,142,143,144,145,146,147,148,149,150,151,152],"elements","agentic webdesign agent elements","MCP","ai agent","registry","search","streaming","open source","open","Bash","plan","subagent","edit","install","input","lock","source",{"skillNo":154,"name":155,"nameZh":6,"description":156,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":157,"categories":158,"keywords":163,"publishedAt":27},"01M6JFCQC7H65M9QJ6TRE71BS1","vercel-deployment","Deploy static sites and frontends to Vercel — handles both CLI and REST API paths, including the CLI token sanitization workaround.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fsoftware-development\u002Fvercel-deployment\u002FSKILL.md",[159,162],{"categoryNo":160,"categoryName":161,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":71,"categoryName":72,"taxonomyType":65,"taxonomyTypeDesc":66},[164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183],"deployment","vercel deployment","vercel","macos","cli","linux","windows","deploy","vercel deploy","REST","api","site","deploy to vercel","token","rest api","host","sites","paths","sanitization","static site",{"skillNo":185,"name":186,"nameZh":6,"description":187,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":188,"categories":189,"keywords":191,"publishedAt":27},"01M6JFCM4SMTXBM5A01BK2YQG1","software-quality-workflows","Umbrella workflow for TDD, debugging, code simplification, spikes, pre-commit review, and debugger-assisted investigation.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fsoftware-development\u002Fsoftware-quality-workflows\u002FSKILL.md",[190],{"categoryNo":71,"categoryName":72,"taxonomyType":65,"taxonomyTypeDesc":66},[192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,25],"workflows","quality","software","software quality workflows","review","tdd","workflow","commit","debugging","code","debugger","pre-commit","investigation","code simplification","user","simplification",{"skillNo":209,"name":210,"nameZh":6,"description":211,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":212,"categories":213,"keywords":221,"publishedAt":27},"01M6JFCGD0M6CEATY01W7YN6DB","react-component-refactoring","Safely refactor large React components into smaller, maintainable pieces using proven patterns","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fsoftware-development\u002Freact-component-refactoring\u002FSKILL.md",[214,217,220],{"categoryNo":215,"categoryName":216,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":218,"categoryName":219,"taxonomyType":65,"taxonomyTypeDesc":66},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":71,"categoryName":72,"taxonomyType":65,"taxonomyTypeDesc":66},[222,223,224,225,226,227,228,229,167,230,231,114,232,170,233,201,234,235,20,236],"react","component","refactoring","component refactoring","react component","react component refactoring","frontend","writing","safe","typescript","react components","modular","refactor","simplify","test-driven-development"]