writing-go について
writing-go は、Go 開発者向けのスキル資料です。標準ライブラリの優先、合成、コンテキスト付きエラーなどの原則を示し、コード例、Go 1.25 の情報、ツール、注意点をまとめています。
主な機能
- 01コンテキスト付きエラー処理
- 02オプションパターンとテーブル駆動テストの例
- 03Go 1.25 の機能概要
- 04ビルド、テスト、lint ツール
- 05並行処理と標準ライブラリの注意点
活用シーン
- 01Go プロジェクトの開発規約を定める
- 02関数やサービスのエラー処理を設計する
- 03テーブル駆動テストと並行コードを確認する
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ julianobarbosa/ claude-code-skills --skill writing-goインストール後、Claude Code で/writing-goを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
CLI.mdPATTERNS.mdTESTING.md詳細
Go 開発(1.25+)
基本原則
- 標準ライブラリ優先:正当な理由がある場合に限り、外部依存関係を追加します
- 具体的な型:インターフェースは利用側で定義し、構造体を返します
- コンポジション:継承ではなく、常にコンポジションを使います
- 早期に失敗:コンテキストを含む明確なエラーを返します
- シンプルに:たいていの場合、最もわかりやすい解決策が正解です
クイックパターン
エラー処理
if err := doThing(); err != nil {
return fmt.Errorf("do thing: %w", err)
}
オプション付き構造体
type Server struct {
addr string
timeout time.Duration
}
func NewServer(addr string, opts ...Option) *Server {
s := &Server{addr: addr, timeout: 30 * time.Second}
for _, opt := range opts {
opt(s)
}
return s
}
テーブル駆動テスト
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"valid", "hello", "HELLO", false},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Process(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
Go 1.25 の機能
- testing/synctest:シミュレートされたクロックを使った決定論的な並行テスト
- encoding/json/v2:実験的機能。3~10 倍高速(GOEXPERIMENT=jsonv2)
- runtime/trace.FlightRecorder:本番環境のトレースをオンデマンドで取得
- コンテナ対応 GOMAXPROCS:cgroup の制限を自動検出
- GreenTea GC:実験的機能。レイテンシを低減(GOEXPERIMENT=greenteagc)
参考資料
- PATTERNS.md - 詳細なコードパターン
- TESTING.md - testify/mockery を使ったテスト戦略
- CLI.md - CLI アプリケーションのパターン
ツール
go build ./... # Build
go test -race ./... # Test with race detector
golangci-lint run # Lint
mockery --all # Generate mocks
注意点
nilチャネルへの送受信は永遠にブロックされます。クローズ済みのチャネルから受信すると、ゼロ値がすぐに返ります —nilチャネルのケースを含むselectは、そのケースを無効にします。便利なパターンですが、意図せずそうしてしまいやすいので注意してください。deferは実行時ではなく、呼び出し時に引数をキャプチャします —defer fmt.Println(time.Now())は、遅延実行時ではなく、今の時刻をキャプチャします。- Go 1.22 より前では、for ループ内のクロージャは、すべての反復で同じ変数をキャプチャします — これが、ループ内で goroutine を使うときのバグの原因です。Go 1.22 でセマンティクスが変更されました。以前の習慣が、複数のバージョンが混在するコードで微妙なバグを生むことがあります。
errors.IsはUnwrap()のチェーンをたどりますが、ラップされたエラーが独自にIs(target error) boolを実装している場合は、チェーンをたどる代わりにそのカスタムIsが優先されます — xerrors から移行するときに混乱しやすい点です。sync.Poolのアイテムは、Getから次のPutまでの間に GC で回収されることがあります — Pool が状態を保持することを前提にしてはいけません。
コメント
Markdown 対応