Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 11480] ファイルの概要

このコミットは、Go言語のドキュメンテーションツールであるgodocに、URLパラメータm=methodsを追加するものです。この新しいモードを有効にすると、godocが生成するドキュメンテーションにおいて、エクスポートされていない匿名フィールドのメソッドを含む、すべての埋め込みメソッドが表示されるようになります。

コミット

commit ff451e8670cff9f825706b193657c8b2129310f8
Author: Robert Griesemer <gri@golang.org>
Date:   Mon Jan 30 14:07:50 2012 -0800

    godoc: add URL mode m=methods
    
    If set, all methods are shown, not just those
    of non-exported anonynous fields.
    
    This change will only become functional once
    CL 5576057 is submitted.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/5599048

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/ff451e8670cff9f825706b193657c8b2129310f8

元コミット内容

godocツールにm=methodsという新しいURLモードを追加します。このモードが設定されると、エクスポートされていない匿名フィールドのメソッドだけでなく、すべてのメソッドが表示されるようになります。この変更は、関連する変更リスト(CL 5576057)がコミットされて初めて機能します。

変更の背景

godocはGo言語のコードからドキュメンテーションを自動生成する非常に便利なツールです。しかし、Goの構造体(struct)における匿名フィールド(embedded fields)とメソッドの埋め込み(method embedding)の仕組みにより、特定の状況下では、開発者が期待するすべてのメソッドがドキュメンテーションに表示されないという問題がありました。

特に、エクスポートされていない(unexported)匿名フィールドに定義されたメソッドは、そのフィールドが埋め込まれた構造体から呼び出すことが可能ですが、godocのデフォルトの挙動では、これらのメソッドがドキュメンテーションから除外される傾向がありました。これは、通常、エクスポートされていない要素は内部実装の詳細と見なされ、公開APIの一部ではないという考え方に基づいています。

しかし、場合によっては、これらの「隠れた」メソッドもドキュメンテーションに含めることが望ましいことがあります。例えば、ライブラリの内部構造を深く理解したい開発者や、特定のデバッグシナリオにおいて、すべてのメソッドの存在を把握したい場合などです。

このコミットは、このようなニーズに応えるため、ユーザーが明示的にすべてのメソッドを表示させるためのオプションを提供することを目的としています。これにより、godocの柔軟性が向上し、より詳細なドキュメンテーションの閲覧が可能になります。

前提知識の解説

1. godocとは

godocは、Go言語のソースコードからドキュメンテーションを生成し、ウェブサーバーとして提供するツールです。Goのコードは、特定のコメント規約(Go Docコメント)に従って記述することで、godocによって自動的に解析され、整形されたドキュメンテーションとして表示されます。これにより、開発者はコードとドキュメンテーションを密接に連携させ、常に最新の状態に保つことができます。

2. Go言語の匿名フィールドとメソッドの埋め込み

Go言語の構造体は、他の構造体を匿名フィールドとして埋め込むことができます。これにより、埋め込まれた構造体のフィールドやメソッドが、外側の構造体に「昇格(promote)」され、あたかも外側の構造体自身のメンバーであるかのように直接アクセスできるようになります。

例:

type Inner struct {
    value int
}

func (i Inner) GetValue() int {
    return i.value
}

type Outer struct {
    Inner // 匿名フィールドとしてInnerを埋め込み
    name  string
}

func main() {
    o := Outer{Inner: Inner{value: 10}, name: "test"}
    fmt.Println(o.GetValue()) // OuterのインスタンスからInnerのメソッドを直接呼び出せる
}

この仕組みは、Goにおけるオブジェクト指向的な「継承」に似た機能を提供しますが、実際にはコンポジション(合成)の一種です。

3. エクスポートされた識別子とエクスポートされていない識別子

Go言語では、識別子(変数名、関数名、型名など)の最初の文字が大文字である場合、その識別子は「エクスポートされている(exported)」と見なされ、パッケージ外からアクセス可能です。最初の文字が小文字である場合、「エクスポートされていない(unexported)」と見なされ、その識別子は定義されたパッケージ内でのみアクセス可能です。

godocは通常、公開APIを重視するため、エクスポートされた識別子のみをドキュメンテーションに含める傾向があります。しかし、匿名フィールドのメソッドの場合、埋め込まれたフィールド自体がエクスポートされていなくても、そのメソッドは外側の構造体から呼び出し可能であるため、ドキュメンテーションの対象とするかどうかが問題となります。

4. docパッケージ

Goの標準ライブラリには、go/docパッケージが存在します。このパッケージは、Goのソースコードを解析し、ドキュメンテーションツリーを構築するための低レベルな機能を提供します。godocツールはこのgo/docパッケージを利用して、実際のドキュメンテーション情報を抽出しています。

技術的詳細

このコミットは、godocのウェブインターフェースにおける表示モードを制御するための新しいURLパラメータm=methodsを導入します。この機能を実現するために、主に以下の2つのファイルが変更されています。

  1. src/cmd/godoc/doc.go:

    • このファイルは、godocのURLパラメータmに関するドキュメンテーションを記述しています。
    • 変更点として、mパラメータのオプションリストにmethodsが追加され、「エクスポートされていない匿名フィールドのメソッドだけでなく、すべての埋め込みメソッドを表示する」という説明が加えられています。これはユーザー向けの機能説明となります。
  2. src/cmd/godoc/godoc.go:

    • このファイルはgodocの主要なロジックを含んでいます。
    • PageInfoMode列挙型へのallMethodsフラグの追加: PageInfoModeは、godocがページ情報を生成する際の様々な表示モードをビットフラグとして定義する列挙型です。ここにallMethodsという新しいフラグが追加されました。
      const (
          noFiltering PageInfoMode = 1 << iota // do not filter exports
          allMethods                           // show all embedded methods
          showSource                           // show source code, do not extract documentation
          noHtml                               // show result in textual form, do not generate HTML
          flatDir                              // show directory in a flat (non-indented) manner
      )
      
    • modeNamesマップへの"methods"エントリの追加: modeNamesマップは、URLパラメータの文字列(例: "all", "src")と、それに対応する内部のPageInfoModeフラグをマッピングします。ここに"methods": allMethodsというエントリが追加され、URLでm=methodsが指定された場合に、内部的にallMethodsフラグが設定されるようになります。
      var modeNames = map[string]PageInfoMode{
          "all":     noFiltering,
          "methods": allMethods, // <-- New entry
          "src":     showSource,
          "text":    noHtml,
          "flat":    flatDir,
      }
      
    • getPageInfo関数でのdoc.AllMethodsフラグの適用: getPageInfo関数は、HTTPリクエストからページ情報を抽出し、go/docパッケージのdoc.New関数に渡すためのモードを決定します。 この関数内で、新しく追加されたallMethodsフラグがチェックされます。もしmode変数にallMethodsフラグが立っていれば(つまり、URLでm=methodsが指定されていれば)、doc.AllMethodsというフラグがm変数にビットOR演算で追加されます。
      if mode&allMethods != 0 {
          m |= doc.AllMethods
      }
      pdoc = doc.New(pkg, path.Clean(relpath), m) // no trailing '/' in importpath
      
      ここで重要なのは、doc.AllMethodsというフラグがgo/docパッケージ(このコミットの時点ではまだ存在しないが、関連するCL 5576057で追加される)に定義されていることです。このコミットは、godocがこの新しいdoc.AllMethodsフラグを認識し、それをgo/docパッケージに渡すための橋渡しをする役割を担っています。

関連する変更リスト (CL 5576057)

コミットメッセージにも明記されている通り、この変更は単独では機能しません。このコミットが完全に機能するためには、別の変更リスト(Change List)であるCL 5576057がGoのリポジトリにコミットされる必要があります。

CL 5576057は、go/docパッケージにAllMethodsという新しいフラグを導入するものです。このフラグは、doc.New関数に渡されることで、go/docパッケージがドキュメンテーションを生成する際に、エクスポートされていない匿名フィールドのメソッドを含むすべてのメソッドを考慮するように指示します。

つまり、このコミット(ff451e8670cff9f825706b193657c8b2129310f8)はgodocのユーザーインターフェースと内部ロジックを準備し、CL 5576057はドキュメンテーション解析のコア部分に実際の機能を追加するという、2段階の変更の一部となっています。

コアとなるコードの変更箇所

src/cmd/godoc/doc.go

--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -131,7 +131,8 @@ shown, and only an identifier index but no full text search index is created.
 The presentation mode of web pages served by godoc can be controlled with the
 "m" URL parameter; it accepts a comma-separated list of flag names as value:
 
-	all	show documentation for all (not just exported) declarations
+	all	show documentation for all declarations, not just the exported ones
+	methods	show all embedded methods, not just those of unexported anonymous fields
 	src	show the original source code rather then the extracted documentation
 	text	present the page in textual (command-line) form rather than HTML
 	flat	present flat (not indented) directory listings using full paths

src/cmd/godoc/godoc.go

--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -867,6 +867,7 @@ type PageInfoMode uint
 
 const (
 	noFiltering PageInfoMode = 1 << iota // do not filter exports
+	allMethods                           // show all embedded methods
 	showSource                           // show source code, do not extract documentation
 	noHtml                               // show result in textual form, do not generate HTML
 	flatDir                              // show directory in a flat (non-indented) manner
@@ -874,10 +875,11 @@ const (
 
 // modeNames defines names for each PageInfoMode flag.
 var modeNames = map[string]PageInfoMode{
-	"all":  noFiltering,
-	"src":  showSource,
-	"text": noHtml,
-	"flat": flatDir,
+	"all":     noFiltering,
+	"methods": allMethods, // <-- New entry
+	"src":     showSource,
+	"text":    noHtml,
+	"flat":    flatDir,
 }
 
 // getPageInfoMode computes the PageInfoMode flags by analyzing the request
@@ -1088,6 +1090,9 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
 		if mode&noFiltering != 0 {
 			m = doc.AllDecls
 		}
+		if mode&allMethods != 0 {
+			m |= doc.AllMethods // <-- Apply doc.AllMethods flag
+		}
 		pdoc = doc.New(pkg, path.Clean(relpath), m) // no trailing '/' in importpath
 	} else {
 		// show source code

コアとなるコードの解説

  1. src/cmd/godoc/doc.goの変更:

    • この変更は、godocのウェブインターフェースのヘルプテキストを更新するものです。
    • m URLパラメータの利用可能なオプションとして、新しくmethodsが追加され、その機能(「エクスポートされていない匿名フィールドのメソッドだけでなく、すべての埋め込みメソッドを表示する」)が説明されています。これにより、ユーザーはこの新機能の存在と使い方をgodoc自身のドキュメンテーションを通じて知ることができます。
  2. src/cmd/godoc/godoc.goの変更:

    • PageInfoModeへのallMethodsの追加: PageInfoModeは、godocがドキュメンテーションを生成する際の内部的な表示モードを管理するためのビットフラグの集合です。allMethodsという新しいフラグが追加され、これが設定されると、すべての埋め込みメソッドを表示するという意図が示されます。
    • modeNamesマップへの"methods"エントリの追加: modeNamesは、URLクエリパラメータの文字列(例: m=methodsmethods部分)を、対応するPageInfoModeのビットフラグにマッピングするためのマップです。このエントリが追加されたことで、ユーザーがURLでm=methodsを指定すると、godocの内部でallMethodsフラグが有効になります。
    • getPageInfo関数でのロジック追加: getPageInfo関数は、HTTPリクエストから現在の表示モードを解析し、go/docパッケージのdoc.New関数に渡すための適切なフラグを構築します。
      • if mode&allMethods != 0という条件文が追加されています。これは、現在のmode(URLパラメータから解析されたもの)にallMethodsフラグが立っているかどうかをチェックします。
      • もしallMethodsフラグが立っていれば、m |= doc.AllMethodsという行が実行されます。これは、doc.New関数に渡される最終的なモード変数mに、go/docパッケージが提供するdoc.AllMethodsフラグをビットOR演算で追加するものです。
      • このdoc.AllMethodsフラグがgo/docパッケージに渡されることで、go/docパッケージは、通常はフィルタリングされるエクスポートされていない匿名フィールドのメソッドもドキュメンテーションに含めるようになります。

これらの変更により、godocはURLパラメータを通じて、より詳細なメソッド表示を制御できるようになり、Go言語のドキュメンテーションの柔軟性が向上しました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメンテーション (godocコマンドのヘルプやgo/docパッケージのドキュメンテーション)
  • Go言語の匿名フィールドとメソッドの埋め込みに関する解説記事
  • Go言語のエクスポートルールに関する解説記事
  • Go言語の変更リスト (Change List, CL) のレビューシステム (Gerrit) の利用方法
  • GitHubのコミット履歴と差分表示機能