Go言語入門:Goドキュメント -一般的な間違いと落とし穴-

スポンサーリンク
Go言語入門:Goドキュメント -一般的な間違いと落とし穴- ノウハウ
Go言語入門:Goドキュメント -一般的な間違いと落とし穴-
この記事は約8分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

本日は、Go言語を効果的に使うためのガイドラインについて解説しています。

スポンサーリンク

背景

Go言語を学び始めて、より良いコードを書きたいと思い、Go言語の公式ドキュメント「Effective Go」を知りました。これは、いわば「Goらしいコードの書き方指南書」になります。単に動くコードではなく、効率的で保守性の高いコードを書くためのベストプラクティスが詰まっているので、これを読んだ時の内容を備忘として残しました。

Docコメント

「Docコメント」は、トップレベルのpackage、const、func、type、var宣言の直前に、改行を挟まずに現れるコメントです。エクスポートされた(大文字で始まる)すべての名前には、docコメントが必要です。

go/docとgo/doc/commentパッケージは、Goソースコードからドキュメントを抽出する機能を提供し、様々なツールがこの機能を利用しています。go docコマンドは、指定されたパッケージやシンボルのdocコメントを検索して表示します。(シンボルとは、トップレベルのconst、func、type、varのことです。)ウェブサーバー pkg.go.dev は、公開Goパッケージのドキュメントを表示します(ライセンスが許可する場合)。そのサイトを提供しているプログラムは golang.org/x/pkgsite/cmd/pkgsite で、プライベートモジュールのドキュメントを表示したり、インターネット接続なしで使用したりするために、ローカルで実行することもできます。言語サーバー gopls は、IDEでGoソースファイルを編集する際にドキュメントを提供します。

このページの残りの部分では、Go docコメントの書き方を説明しています。

Go言語ドキュメントコメントの一般的な間違いと落とし穴

基本ルールと問題の背景

ドキュメントコメント内でインデント(字下げ)されているか空白行がある部分は、コードブロックとして表示されるというルールは、Goの初期から存在していました。しかし、gofmtがドキュメントコメントに対応していなかったため、意図せずにコードブロックを作成してしまう既存のコメントが多数存在していました。

1. インデントされていないリスト

package http

// cancelTimerBody is an io.ReadCloser that wraps rc with two features:
// 1) On Read error or close, the stop func is called.
// 2) On Read failure, if reqDidTimeout is true, the error is wrapped and
//    marked as net.Error that hit its timeout.
type cancelTimerBody struct {
    // ...
}

この例では、リストの最後の行「marked as net.Error that hit its timeout.」がインデントされているため、意図せずコードブロックとして表示されていました。

実際の表示結果:

cancelTimerBody is an io.ReadCloser that wraps rc with two features:
1) On Read error or close, the stop func is called. 2) On Read failure,
if reqDidTimeout is true, the error is wrapped and

    marked as net.Error that hit its timeout.

2. 複数行にわたるコマンド

package smtp

// localhostCert is a PEM-encoded TLS cert generated from src/crypto/tls:
//
// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com \
//     --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var localhostCert = []byte(`...`)

この例では、コマンドの2行目がインデントされているため、コードブロックとして扱われていました。

3. JSON例の表示問題

// On the wire, the JSON will look something like this:
// {
//  "kind":"MyAPIObject",
//  "apiVersion":"v1",
//  "myPlugin": {
//      "kind":"PluginA",
//      "aOption":"foo",
//  },
// }

この例では、開始の「{」が段落として扱われ、中身がコードブロック、終了の「}」が別の段落として表示されていました。

Go 1.19での改善

Go 1.19のgofmtでは、これらの問題を解決するためのヒューリスティック(経験則に基づく処理)が導入されました。

改善された表示例

// cancelTimerBody is an io.ReadCloser that wraps rc with two features:
//  1. On Read error or close, the stop func is called.
//  2. On Read failure, if reqDidTimeout is true, the error is wrapped and
//     marked as net.Error that hit its timeout.

// localhostCert is a PEM-encoded TLS cert generated from src/crypto/tls:
//
//  go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com \
//      --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h

// On the wire, the JSON will look something like this:
//
//  {
//      "kind":"MyAPIObject",
//      "apiVersion":"v1",
//      "myPlugin": {
//          "kind":"PluginA",
//          "aOption":"foo",
//      },
//  }

1. 意図しないインデント

間違い例:

// TODO Revisit this design. It may make sense to walk those nodes
//      only once.

修正方法: 2行目のインデントを削除する

2. リストや コードブロックでの改行インデント不足

間違い例:

// Uses of this error model include:
//
//   - Partial errors. If a service needs to return partial errors to the
// client,
//     it may embed the `Status` in the normal response to indicate the
// partial
//     errors.

修正方法: 改行した行も適切にインデントする

ネストしたリストの制限

Goのドキュメントコメントはネストしたリストをサポートしていません

自動変換前:

// Here is a list:
//
//  - Item 1.
//    * Subitem 1.
//    * Subitem 2.
//  - Item 2.
//  - Item 3.

自動変換後:

// Here is a list:
//
//  - Item 1.
//  - Subitem 1.
//  - Subitem 2.
//  - Item 2.
//  - Item 3.

回避策

異なるリストマーカーを使用することで、疑似的なネストを実現できます:

// Here is a list:
//
//  1. Item 1.
//
//     - Subitem 1.
//
//     - Subitem 2.
//
//  2. Item 2.
//
//  3. Item 3.

まとめ

  • ドキュメントコメントでインデントされた行はコードブロックとして表示される
  • Go 1.19以降のgofmtは多くの一般的な間違いを自動修正する
  • 手動での調整が必要な場合もある
  • ネストしたリストは直接サポートされていない
  • 明確な文書化のため、適切なインデントと空白行の使用が重要

重要なポイント

  1. インデントルール: Go言語では、ドキュメントコメント内でインデントされた行は自動的にコードブロックとして表示されます。これは意図しない表示を引き起こす主な原因です。
  2. Go 1.19の改善: 2022年にリリースされたGo 1.19では、gofmtツールがドキュメントコメントを自動修正する機能を追加し、多くの一般的な間違いを解決できるようになりました。
  3. 統計データ: 公開されているGoモジュールの調査では、わずか3%のドキュメントコメントが修正対象となり、その中の87%は適切に修正され、6%程度で問題が発生していました。
  4. 制限事項: Goのドキュメントコメントはネストしたリスト(リストの中にリスト)をサポートしていないため、工夫が必要です。

この知識は、Go言語でライブラリやパッケージを開発する際に、適切なドキュメンテーションを作成するために非常に重要です。

おわりに 

本日は、Go言語を効果的に使うためのガイドラインについて解説しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました