Skills Plugins MCP Prompt Model 博客 我的中心

golang-patterns

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

DeepseekModel Curated skill Quality Excellent · 90 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-ja-jp-skills-golang-patterns-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name golang-patterns description 堅牢で効率的かつ保守可能なGoアプリケーションを構築するための慣用的なGoパターン、ベストプラクティス、規約。 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 {
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。