Source profileQuality 70/100Review permissions

affaan-m/ECC/docs/ja-JP/skills/golang-patterns/SKILL.md

golang-patterns

Review golang-patterns's use cases, installation, workflow, and original source instructions.

Source repository stars
234,327
Declared platforms
0
Static risk flags
3
Last source update
2026-07-27
Source checked
2026-07-28

Decision brief

What it does—and where it fits

堅牢で効率的かつ保守可能なアプリケーションを構築するための慣用的なGoパターンとベストプラクティス。

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/affaan-m/ECC --skill "docs/ja-JP/skills/golang-patterns"
    Safe inspection promptEditorial

    Inspect the Agent Skill "golang-patterns" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/docs/ja-JP/skills/golang-patterns/SKILL.md at commit 4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      いつ有効化するか

      新しいGoコードを書くとき

      新しいGoコードを書くときGoコードをレビューするとき既存のGoコードをリファクタリングするとき
    2. 02

      核となる原則

      Goは巧妙さよりもシンプルさを好みます。コードは明白で読みやすいものであるべきです。

      Goは巧妙さよりもシンプルさを好みます。コードは明白で読みやすいものであるべきです。型を設計する際、そのゼロ値が初期化なしですぐに使用できるようにします。関数はインターフェースパラメータを受け取り、具体的な型を返すべきです。
    3. 03

      1. シンプルさと明確さ

      Goは巧妙さよりもシンプルさを好みます。コードは明白で読みやすいものであるべきです。

      Goは巧妙さよりもシンプルさを好みます。コードは明白で読みやすいものであるべきです。
    4. 04

      2. ゼロ値を有用にする

      型を設計する際、そのゼロ値が初期化なしですぐに使用できるようにします。

      型を設計する際、そのゼロ値が初期化なしですぐに使用できるようにします。
    5. 05

      3. インターフェースを受け取り、構造体を返す

      関数はインターフェースパラメータを受け取り、具体的な型を返すべきです。

      関数はインターフェースパラメータを受け取り、具体的な型を返すべきです。

    Permission review

    Static risk signals and limitations

    Reads files

    low · line 94

    The documentation asks the agent to read local files, directories, or repositories.

    data, err := os.ReadFile(path)

    Network access

    medium · line 205

    The documentation includes network, browsing, or remote request actions.

    return nil, fmt.Errorf("fetch %s: %w", url, err)

    Network access

    medium · line 269

    The documentation includes network, browsing, or remote request actions.

    data, _ := fetch(url)

    Runs scripts

    medium · line 570

    The documentation asks the agent to run terminal commands or scripts.

    go build ./...

    Runs scripts

    medium · line 571

    The documentation asks the agent to run terminal commands or scripts.

    go run ./cmd/myapp

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score70/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars234,327SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    affaan-m/ECC
    Skill path
    docs/ja-JP/skills/golang-patterns/SKILL.md
    Commit
    4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38
    License
    MIT
    Collected
    2026-07-28
    Default branch
    main
    View the original SKILL.md

    Go開発パターン

    堅牢で効率的かつ保守可能なアプリケーションを構築するための慣用的なGoパターンとベストプラクティス。

    いつ有効化するか

    • 新しいGoコードを書くとき
    • Goコードをレビューするとき
    • 既存のGoコードをリファクタリングするとき
    • Goパッケージ/モジュールを設計するとき

    核となる原則

    1. シンプルさと明確さ

    Goは巧妙さよりもシンプルさを好みます。コードは明白で読みやすいものであるべきです。

    // Good: Clear and direct
    func GetUser(id string) (*User, error) {
        user, err := db.FindUser(id)
        if err != nil {
            return nil, fmt.Errorf("get user %s: %w", id, err)
        }
        return user, nil
    }
    
    // Bad: Overly clever
    func GetUser(id string) (*User, error) {
        return func() (*User, error) {
            if u, e := db.FindUser(id); e == nil {
                return u, nil
            } else {
                return nil, e
            }
        }()
    }
    

    2. ゼロ値を有用にする

    型を設計する際、そのゼロ値が初期化なしですぐに使用できるようにします。

    // Good: Zero value is useful
    type Counter struct {
        mu    sync.Mutex
        count int // zero value is 0, ready to use
    }
    
    func (c *Counter) Inc() {
        c.mu.Lock()
        c.count++
        c.mu.Unlock()
    }
    
    // Good: bytes.Buffer works with zero value
    var buf bytes.Buffer
    buf.WriteString("hello")
    
    // Bad: Requires initialization
    type BadCounter struct {
        counts map[string]int // nil map will panic
    }
    

    3. インターフェースを受け取り、構造体を返す

    関数はインターフェースパラメータを受け取り、具体的な型を返すべきです。

    // Good: Accepts interface, returns concrete type
    func ProcessData(r io.Reader) (*Result, error) {
        data, err := io.ReadAll(r)
        if err != nil {
            return nil, err
        }
        return &Result{Data: data}, nil
    }
    
    // Bad: Returns interface (hides implementation details unnecessarily)
    func ProcessData(r io.Reader) (io.Reader, error) {
        // ...
    }
    

    エラーハンドリングパターン

    コンテキスト付きエラーラッピング

    // Good: Wrap errors with context
    func LoadConfig(path string) (*Config, error) {
        data, err := os.ReadFile(path)
        if err != nil {
            return nil, fmt.Errorf("load config %s: %w", path, err)
        }
    
        var cfg Config
        if err := json.Unmarshal(data, &cfg); err != nil {
            return nil, fmt.Errorf("parse config %s: %w", path, err)
        }
    
        return &cfg, nil
    }
    

    カスタムエラー型

    // Define domain-specific errors
    type ValidationError struct {
        Field   string
        Message string
    }
    
    func (e *ValidationError) Error() string {
        return fmt.Sprintf("validation failed on %s: %s", e.Field, e.Message)
    }
    
    // Sentinel errors for common cases
    var (
        ErrNotFound     = errors.New("resource not found")
        ErrUnauthorized = errors.New("unauthorized")
        ErrInvalidInput = errors.New("invalid input")
    )
    

    errors.IsとErrors.Asを使用したエラーチェック

    func HandleError(err error) {
        // Check for specific error
        if errors.Is(err, sql.ErrNoRows) {
            log.Println("No records found")
            return
        }
    
        // Check for error type
        var validationErr *ValidationError
        if errors.As(err, &validationErr) {
            log.Printf("Validation error on field %s: %s",
                validationErr.Field, validationErr.Message)
            return
        }
    
        // Unknown error
        log.Printf("Unexpected error: %v", err)
    }
    

    エラーを決して無視しない

    // Bad: Ignoring error with blank identifier
    result, _ := doSomething()
    
    // Good: Handle or explicitly document why it's safe to ignore
    result, err := doSomething()
    if err != nil {
        return err
    }
    
    // Acceptable: When error truly doesn't matter (rare)
    _ = writer.Close() // Best-effort cleanup, error logged elsewhere
    

    並行処理パターン

    ワーカープール

    func WorkerPool(jobs <-chan Job, results chan<- Result, numWorkers int) {
        var wg sync.WaitGroup
    
        for i := 0; i < numWorkers; i++ {
            wg.Add(1)
            go func() {
                defer wg.Done()
                for job := range jobs {
                    results <- process(job)
                }
            }()
        }
    
        wg.Wait()
        close(results)
    }
    

    キャンセルとタイムアウト用のContext

    func FetchWithTimeout(ctx context.Context, url string) ([]byte, error) {
        ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
        defer cancel()
    
        req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
        if err != nil {
            return nil, fmt.Errorf("create request: %w", err)
        }
    
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            return nil, fmt.Errorf("fetch %s: %w", url, err)
        }
        defer resp.Body.Close()
    
        return io.ReadAll(resp.Body)
    }
    

    グレースフルシャットダウン

    func GracefulShutdown(server *http.Server) {
        quit := make(chan os.Signal, 1)
        signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    
        <-quit
        log.Println("Shutting down server...")
    
        ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
        defer cancel()
    
        if err := server.Shutdown(ctx); err != nil {
            log.Fatalf("Server forced to shutdown: %v", err)
        }
    
        log.Println("Server exited")
    }
    

    協調的なGoroutine用のerrgroup

    import "golang.org/x/sync/errgroup"
    
    func FetchAll(ctx context.Context, urls []string) ([][]byte, error) {
        g, ctx := errgroup.WithContext(ctx)
        results := make([][]byte, len(urls))
    
        for i, url := range urls {
            i, url := i, url // Capture loop variables
            g.Go(func() error {
                data, err := FetchWithTimeout(ctx, url)
                if err != nil {
                    return err
                }
                results[i] = data
                return nil
            })
        }
    
        if err := g.Wait(); err != nil {
            return nil, err
        }
        return results, nil
    }
    

    Goroutineリークの回避

    // Bad: Goroutine leak if context is cancelled
    func leakyFetch(ctx context.Context, url string) <-chan []byte {
        ch := make(chan []byte)
        go func() {
            data, _ := fetch(url)
            ch <- data // Blocks forever if no receiver
        }()
        return ch
    }
    
    // Good: Properly handles cancellation
    func safeFetch(ctx context.Context, url string) <-chan []byte {
        ch := make(chan []byte, 1) // Buffered channel
        go func() {
            data, err := fetch(url)
            if err != nil {
                return
            }
            select {
            case ch <- data:
            case <-ctx.Done():
            }
        }()
        return ch
    }
    

    インターフェース設計

    小さく焦点を絞ったインターフェース

    // Good: Single-method interfaces
    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    
    type Writer interface {
        Write(p []byte) (n int, err error)
    }
    
    type Closer interface {
        Close() error
    }
    
    // Compose interfaces as needed
    type ReadWriteCloser interface {
        Reader
        Writer
        Closer
    }
    

    使用する場所でインターフェースを定義

    // In the consumer package, not the provider
    package service
    
    // UserStore defines what this service needs
    type UserStore interface {
        GetUser(id string) (*User, error)
        SaveUser(user *User) error
    }
    
    type Service struct {
        store UserStore
    }
    
    // Concrete implementation can be in another package
    // It doesn't need to know about this interface
    

    型アサーションを使用してオプション動作を実装

    type Flusher interface {
        Flush() error
    }
    
    func WriteAndFlush(w io.Writer, data []byte) error {
        if _, err := w.Write(data); err != nil {
            return err
        }
    
        // Flush if supported
        if f, ok := w.(Flusher); ok {
            return f.Flush()
        }
        return nil
    }
    

    パッケージ構成

    標準プロジェクトレイアウト

    myproject/
    ├── cmd/
    │   └── myapp/
    │       └── main.go           # エントリポイント
    ├── internal/
    │   ├── handler/              # HTTP ハンドラー
    │   ├── service/              # ビジネスロジック
    │   ├── repository/           # データアクセス
    │   └── config/               # 設定
    ├── pkg/
    │   └── client/               # 公開 API クライアント
    ├── api/
    │   └── v1/                   # API 定義(proto、OpenAPI)
    ├── testdata/                 # テストフィクスチャ
    ├── go.mod
    ├── go.sum
    └── Makefile
    

    パッケージ命名

    // Good: Short, lowercase, no underscores
    package http
    package json
    package user
    
    // Bad: Verbose, mixed case, or redundant
    package httpHandler
    package json_parser
    package userService // Redundant 'Service' suffix
    

    パッケージレベルの状態を避ける

    // Bad: Global mutable state
    var db *sql.DB
    
    func init() {
        db, _ = sql.Open("postgres", os.Getenv("DATABASE_URL"))
    }
    
    // Good: Dependency injection
    type Server struct {
        db *sql.DB
    }
    
    func NewServer(db *sql.DB) *Server {
        return &Server{db: db}
    }
    

    構造体設計

    関数型オプションパターン

    type Server struct {
        addr    string
        timeout time.Duration
        logger  *log.Logger
    }
    
    type Option func(*Server)
    
    func WithTimeout(d time.Duration) Option {
        return func(s *Server) {
            s.timeout = d
        }
    }
    
    func WithLogger(l *log.Logger) Option {
        return func(s *Server) {
            s.logger = l
        }
    }
    
    func NewServer(addr string, opts ...Option) *Server {
        s := &Server{
            addr:    addr,
            timeout: 30 * time.Second, // default
            logger:  log.Default(),    // default
        }
        for _, opt := range opts {
            opt(s)
        }
        return s
    }
    
    // Usage
    server := NewServer(":8080",
        WithTimeout(60*time.Second),
        WithLogger(customLogger),
    )
    

    コンポジション用の埋め込み

    type Logger struct {
        prefix string
    }
    
    func (l *Logger) Log(msg string) {
        fmt.Printf("[%s] %s\n", l.prefix, msg)
    }
    
    type Server struct {
        *Logger // Embedding - Server gets Log method
        addr    string
    }
    
    func NewServer(addr string) *Server {
        return &Server{
            Logger: &Logger{prefix: "SERVER"},
            addr:   addr,
        }
    }
    
    // Usage
    s := NewServer(":8080")
    s.Log("Starting...") // Calls embedded Logger.Log
    

    メモリとパフォーマンス

    サイズがわかっている場合はスライスを事前割り当て

    // Bad: Grows slice multiple times
    func processItems(items []Item) []Result {
        var results []Result
        for _, item := range items {
            results = append(results, process(item))
        }
        return results
    }
    
    // Good: Single allocation
    func processItems(items []Item) []Result {
        results := make([]Result, 0, len(items))
        for _, item := range items {
            results = append(results, process(item))
        }
        return results
    }
    

    頻繁な割り当て用のsync.Pool使用

    var bufferPool = sync.Pool{
        New: func() interface{} {
            return new(bytes.Buffer)
        },
    }
    
    func ProcessRequest(data []byte) []byte {
        buf := bufferPool.Get().(*bytes.Buffer)
        defer func() {
            buf.Reset()
            bufferPool.Put(buf)
        }()
    
        buf.Write(data)
        // Process...
        return buf.Bytes()
    }
    

    ループ内での文字列連結を避ける

    // Bad: Creates many string allocations
    func join(parts []string) string {
        var result string
        for _, p := range parts {
            result += p + ","
        }
        return result
    }
    
    // Good: Single allocation with strings.Builder
    func join(parts []string) string {
        var sb strings.Builder
        for i, p := range parts {
            if i > 0 {
                sb.WriteString(",")
            }
            sb.WriteString(p)
        }
        return sb.String()
    }
    
    // Best: Use standard library
    func join(parts []string) string {
        return strings.Join(parts, ",")
    }
    

    Goツール統合

    基本コマンド

    # Build and run
    go build ./...
    go run ./cmd/myapp
    
    # Testing
    go test ./...
    go test -race ./...
    go test -cover ./...
    
    # Static analysis
    go vet ./...
    staticcheck ./...
    golangci-lint run
    
    # Module management
    go mod tidy
    go mod verify
    
    # Formatting
    gofmt -w .
    goimports -w .
    

    推奨リンター設定(.golangci.yml)

    linters:
      enable:
        - errcheck
        - gosimple
        - govet
        - ineffassign
        - staticcheck
        - unused
        - gofmt
        - goimports
        - misspell
        - unconvert
        - unparam
    
    linters-settings:
      errcheck:
        check-type-assertions: true
      govet:
        enable:
          - shadow
    
    issues:
      exclude-use-default: false
    

    クイックリファレンス:Goイディオム

    イディオム説明
    インターフェースを受け取り、構造体を返す関数はインターフェースパラメータを受け取り、具体的な型を返す
    エラーは値であるエラーを例外ではなく一級値として扱う
    メモリ共有で通信しないgoroutine間の調整にチャネルを使用
    ゼロ値を有用にする型は明示的な初期化なしで機能すべき
    少しのコピーは少しの依存よりも良い不要な外部依存を避ける
    明確さは巧妙さよりも良い巧妙さよりも可読性を優先
    gofmtは誰の好みでもないが皆の友達常にgofmt/goimportsでフォーマット
    早期リターンエラーを最初に処理し、ハッピーパスのインデントを浅く保つ

    避けるべきアンチパターン

    // Bad: Naked returns in long functions
    func process() (result int, err error) {
        // ... 50 lines ...
        return // What is being returned?
    }
    
    // Bad: Using panic for control flow
    func GetUser(id string) *User {
        user, err := db.Find(id)
        if err != nil {
            panic(err) // Don't do this
        }
        return user
    }
    
    // Bad: Passing context in struct
    type Request struct {
        ctx context.Context // Context should be first param
        ID  string
    }
    
    // Good: Context as first parameter
    func ProcessRequest(ctx context.Context, id string) error {
        // ...
    }
    
    // Bad: Mixing value and pointer receivers
    type Counter struct{ n int }
    func (c Counter) Value() int { return c.n }    // Value receiver
    func (c *Counter) Increment() { c.n++ }        // Pointer receiver
    // Pick one style and be consistent
    

    覚えておいてください: Goコードは最良の意味で退屈であるべきです - 予測可能で、一貫性があり、理解しやすい。迷ったときは、シンプルに保ってください。

    Alternatives

    Compare before choosing