go-best-practices について
go-best-practicesは、Go向けの言語別コーディングスキルです。CLAUDE.mdにある型優先、関数型、エラー処理のパターンに基づき、状態のモデル化、インターフェース、エラーチェーン、構造化ログを解説します。
主な機能
- 01ドメイン値に独自型を使う方法
- 02インターフェースによる振る舞いの定義
- 03関数オプションとコンポジションの適用
- 04エラーチェーンを保つラップ方法
- 05log/slogによる構造化ログ
活用シーン
- 01異なる型によるドメインIDのモデル化
- 02依存関係のインターフェース設計
- 03呼び出しをまたいだエラー情報の保持
- 04キーと値による構造化ログの追加
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ alleneubank/ claude-code --skill go-best-practicesインストール後、Claude Code で/go-best-practicesを入力して読み込まれたか確認します。
詳細
Go のベストプラクティス
CLAUDE.md の型優先、関数型、エラー処理のパターンに従います。このスキルでは、言語固有のイディオムのみを扱います。
不正な状態を表現できないようにする
Go の型システムを使って、無効な状態をコンパイル時に防ぎます。
ドメインプリミティブにはカスタム型を使用します:
// Distinct types prevent mixing up IDs
type UserID string
type OrderID string
func GetUser(id UserID) (*User, error) {
// Compiler prevents passing OrderID here
}
// Methods attach behavior to the type
func (id UserID) String() string {
return string(id)
}
動作の契約にはインターフェースを使用します:
// Define what you need, not what you have
type UserRepository interface {
GetByID(ctx context.Context, id UserID) (*User, error)
Save(ctx context.Context, user *User) error
}
// Accept interfaces, return structs
func ProcessInput(r io.Reader) ([]byte, error) {
return io.ReadAll(r)
}
iota と網羅的な switch を使った列挙型:
type Status int
const (
StatusActive Status = iota + 1
StatusInactive
StatusPending
)
func ProcessStatus(s Status) (string, error) {
switch s {
case StatusActive:
return "processing", nil
case StatusInactive:
return "skipped", nil
case StatusPending:
return "waiting", nil
default:
return "", fmt.Errorf("unhandled status: %v", s)
}
}
柔軟な構築には関数型オプションを使用します:
type ServerOption func(*Server)
func WithPort(port int) ServerOption {
return func(s *Server) { s.port = port }
}
func NewServer(opts ...ServerOption) *Server {
s := &Server{port: 8080, timeout: 30 * time.Second}
for _, opt := range opts {
opt(s)
}
return s
}
// Usage: NewServer(WithPort(3000), WithTimeout(time.Minute))
構成には埋め込みを使用します:
type Timestamps struct {
CreatedAt time.Time
UpdatedAt time.Time
}
type User struct {
Timestamps // User gains CreatedAt, UpdatedAt
ID UserID
Email string
}
Go 固有のエラー処理
%w でエラーをラップし、errors.Is / errors.As でチェーンを保持します:
out, err := client.Do(ctx, req)
if err != nil {
return nil, fmt.Errorf("fetch widget failed: %w", err)
}
構造化ロギング
構造化されたキーと値のペアで log/slog を使用します:
import "log/slog"
var log = slog.With("component", "widgets")
func createWidget(name string) (*Widget, error) {
log.Debug("creating widget", "name", name)
widget := &Widget{Name: name}
log.Debug("created widget", "id", widget.ID)
return widget, nil
}
コメント
Markdown 対応