問題が発生する場所Goの設計では、エラーに正面から向き合うことが求められます。try/catchブロックに依存するJavaやPythonとは異なり、Goの関数は標準的な値としてerrorを返します。初心者はすべてが期待通りに動くと仮定して、これらのチェックをスキップしがちですが、この見落としこそがリンターの警告を引き起こす原因です。
標準のGoコンパイラは、戻り値を未使用の変数に代入しない限り、戻り値を無視してもブロックしません。しかし、golangci-lintのような静的解析ツールはこれを即座に検出します。CIパイプラインやIDEのターミナルでエラーが発生するのを目にすることになるでしょう。
// このコードは警告を発生させます
func saveConfig(data string) {
os.WriteFile("config.yaml", []byte(data), 0644) // エラーが無視されています!
}
チェックを実行すると、おなじみのエラーメッセージが表示されます:
main.go:10:14: Error return value of function os.WriteFile is not checked (errcheck)
分析:サイレントな失敗のリスクエラーを無視することは危険な賭けです。もしディスクがいっぱいだったり、パーミッションエラーなどでos.WriteFileが失敗した場合、プログラムは10MBの設定ファイルが正常に保存されたかのように動作を続けます。これらの「サイレントな失敗」は、クラッシュが通常かなり後になってから、スタックの無関係な部分で発生するため、デバッグにおいて悪夢となります。
エラーが見落とされがちな、以下のハイリスクな関数に注意してください:
Close(): ファイル記述子やデータベース接続のクローズ。-Write(): HTTPレスポンスの送信やディスクへの書き込み。-json.Unmarshal(): バイト列から構造体への変換。-Exec(): データベースのマイグレーションや更新の実行。## クイックフィックス:ブランク識別子プロトタイプ作成中にリンターの警告を止めたいですか?その場合はブランク識別子_を使用します。これはGoに対して「失敗する可能性があることは分かっているが、今はあえて無視する」と伝えることになります。
func prototype(data string) {
_ = os.WriteFile("test.txt", []byte(data), 0644)
}
プロのヒント: これは控えめに使用してください。リンターの警告を抑制しても、根本的なリスクは解決されません。単にツールから見えなくしているだけです。
恒久的な修正:プロフェッショナルなエラーパターン### 1. 標準的なガード節これはGoの基本中の基本です。エラーをすぐにチェックして処理しましょう。後回しにしてはいけません。
func saveConfig(data string) error {
err := os.WriteFile("config.yaml", []byte(data), 0644)
if err != nil {
return fmt.Errorf("設定を保存できませんでした: %w", err)
}
return nil
}
2. Defer内でのエラーキャプチャファイルを閉じる処理は典型的な罠です。単純な defer f.Close() は、最終的なフラッシュ中の潜在的なエラーを無視します。関数がエラーを返す場合は、名前付き戻り変数を使用して、クリーンアップ中の失敗をキャプチャします。
func processFile(path string) (err error) {
f, err := os.Open(path)
if err != nil {
return err
}
defer func() {
closeErr := f.Close()
// メインのエラーが現在nilの場合のみ上書きする
if err == nil {
err = closeErr
}
}()
// ここにファイル処理のロジックを記述
return nil
}
3. 「ログを記録して続行」アプローチバックグラウンドのゴルーチン内など、エラーを上位に伝播させることができない場合があります。そのような場合は、可視化が重要です。エラーをログに記録し、SentryやDatadogのダッシュボードで追跡できるようにします。
defer func() {
if err := r.Body.Close(); err != nil {
log.Printf("重要: ボディのクローズに失敗しました: %v", err)
}
}()
4. 実際に無視しても安全な場合fmt.Printlnが返すエラーをチェックしている人はほとんどいません。標準出力への書き込みが失敗する場合、おそらく環境自体がすでにクラッシュしています。このような稀なケースでリンターを満足させるには、明示的に記述します。
_, _ = fmt.Fprintln(os.Stderr, "緊急ログエントリ")
検証:クリーンな状態の確認パターンを更新したら、業界標準のツールスイートを実行して修正を確認します。golangci-lintをまだ導入していない場合は、2分ほどでセットアップできるので、試す価値があります。
# 有効なすべてのリンターを実行
golangci-lint run ./...
未処理のエラーだけに焦点を当ててチェックするには、errcheckを使用します:
# まだインストールしていない場合はインストール
go install github.com/kisielk/errcheck@latest
# プロジェクトを監査
errcheck ./...
出力がゼロになることが目標です。それは、あなたのコードが堅牢であり、チームが本番環境で「幽霊バグ」を追いかける必要がないことを意味します。

