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

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

このコミットは、Go言語のドキュメンテーションツールである godoc コマンドに、ファイルの内容をプレーンテキスト形式で表示する機能を追加するものです。具体的には、godoc が提供するWebインターフェースにおいて、?m=text クエリパラメータをファイルパスに付与することで、そのファイルのソースコードを整形されていないテキストとして閲覧できるようになります。これにより、パッケージのドキュメントと同様に、個別のファイルについてもプレーンテキストでの表示が可能となり、より柔軟な情報参照が実現されます。

コミット

commit be2596471f352c41b02a57e96c963d16ecb56183
Author: Andrew Gerrand <adg@golang.org>
Date:   Mon Jan 14 09:35:04 2013 +1100

    cmd/godoc: support m=text parameter for text files
    
    It's possible to view the package docs in plain text, eg:
            http://golang.org/pkg/time/?m=text
    and this CL introduces the ability to do the same for files:
            http://golang.org/src/pkg/time/time.go?m=text
    
    R=golang-dev, dave, minux.ma
    CC=golang-dev
    https://golang.org/cl/7085054
---
 src/cmd/godoc/godoc.go | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index e2d489c581..12148ec1cd 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -15,6 +15,7 @@ import (
 	"go/format"
 	"go/printer"
 	"go/token"
+	htmlpkg "html"
 	"io"
 	"io/ioutil"
 	"log"
@@ -681,10 +682,16 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit
 		return
 	}\n 
+\tif r.FormValue("m") == "text" {\n+\t\tserveText(w, src)\n+\t\treturn\n+\t}\n+\n 	var buf bytes.Buffer\n 	buf.WriteString("<pre>")
 	FormatText(&buf, src, 1, pathpkg.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))\n 	buf.WriteString("</pre>")
+\tfmt.Fprintf(&buf, `<p><a href="/%s?m=text">View as plain text</a></p>`, htmlpkg.EscapeString(relpath))\n 
 	servePage(w, Page{\n \t\tTitle:    title + " " + relpath,\n```

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

[https://github.com/golang/go/commit/be2596471f352c41b02a57e96c963d16ecb56183](https://github.com/golang/go/commit/be2596471f352c41b02a57e96c963d16ecb56183)

## 元コミット内容

`cmd/godoc`: テキストファイルに対する `m=text` パラメータのサポート

パッケージのドキュメントは、例えば `http://golang.org/pkg/time/?m=text` のようにプレーンテキストで表示することが可能です。この変更は、ファイルに対しても同様の機能を提供します。例えば、`http://golang.org/src/pkg/time/time.go?m=text` のように利用できます。

## 変更の背景

`godoc` はGo言語のコードからドキュメントを生成し、Webインターフェースを通じて提供するツールです。以前から、パッケージ全体のドキュメントについては、URLに `?m=text` クエリパラメータを追加することで、HTML整形されていないプレーンテキスト形式で表示する機能が提供されていました。これは、プログラムによる解析や、シンプルな表示を求めるユーザーにとって有用な機能でした。

しかし、個別のソースファイル(例えば `.go` ファイル)の内容を `godoc` のWebインターフェースで表示する際には、この `?m=text` パラメータがサポートされていませんでした。そのため、ファイルの内容をプレーンテキストで取得したい場合、ユーザーはブラウザの「ソースを表示」機能を使うか、直接ファイルをダウンロードするなどの手間が必要でした。

このコミットは、この一貫性のない挙動を解消し、パッケージドキュメントと同様に、個別のファイルについても `?m=text` パラメータによるプレーンテキスト表示を可能にすることで、`godoc` の利便性と使いやすさを向上させることを目的としています。これにより、`godoc` のWebインターフェースを通じて、より統一された方法でGoのソースコードやドキュメントにアクセスできるようになります。

## 前提知識の解説

### godoc

`godoc` はGo言語に標準で付属するツールで、Goのソースコードからドキュメンテーションを生成し、表示する役割を担います。Goのコードは、コメントの書き方によって自動的にドキュメントとして認識される仕組みがあり、`godoc` はそのコメントとコード構造を解析して、人間が読みやすい形式で表示します。

`godoc` は主に以下の2つの方法で利用されます。

1.  **コマンドラインツールとして**: `godoc fmt Printf` のようにコマンドラインで実行することで、特定のパッケージや関数のドキュメントをターミナルに表示できます。
2.  **Webサーバーとして**: `godoc -http=:8000` のように実行することで、ローカルマシン上にWebサーバーを立ち上げ、ブラウザを通じてGoの標準ライブラリやGOPATH内のプロジェクトのドキュメントを閲覧できます。Go言語の公式ドキュメントサイト `golang.org/pkg` も `godoc` をベースに構築されています。

### `m=text` パラメータ

`godoc` のWebインターフェースでは、URLにクエリパラメータを追加することで表示形式を制御する機能があります。`m=text` はその一つで、ドキュメントの表示モードを「プレーンテキスト」に切り替えるためのパラメータです。通常、`godoc` はHTML形式でドキュメントを整形して表示しますが、`?m=text` を付与すると、HTMLタグやCSSによる装飾が一切ない、純粋なテキスト形式で内容が出力されます。これは、以下のような場合に特に有用です。

*   **プログラムによる解析**: ドキュメントの内容をスクリプトなどで自動的に取得・解析したい場合、HTMLのパースは複雑ですが、プレーンテキストであれば容易に処理できます。
*   **シンプルな表示**: テキストベースの環境や、装飾を必要としないシンプルな表示を好むユーザーにとって、余計な情報がないプレーンテキストは読みやすい場合があります。
*   **デバッグや確認**: HTMLレンダリングの問題を切り分けたり、純粋なコンテンツを確認したりする際に役立ちます。

### HTTPリクエストとクエリパラメータ

WebブラウザがWebサーバーに情報を要求する際、HTTPプロトコルが使用されます。URL(Uniform Resource Locator)は、Web上のリソースの場所を示すもので、その一部として「クエリパラメータ」を含めることができます。

クエリパラメータは、URLのパス部分の後に `?` を挟んで記述され、`キー=値` の形式で複数のパラメータを `&` で区切って指定できます。例えば、`http://example.com/search?q=golang&sort=date` というURLでは、`q` と `sort` がクエリパラメータであり、それぞれ `golang` と `date` という値を持っています。

Webサーバー側のアプリケーションは、これらのクエリパラメータを解析し、その値に基づいて動的にコンテンツを生成したり、表示形式を変更したりします。今回のコミットでは、`godoc` サーバーが `m=text` というクエリパラメータを検出した場合に、ファイルの表示形式をプレーンテキストに切り替えるように変更されています。

## 技術的詳細

このコミットの技術的な核心は、`godoc` のWebサーバーハンドラがファイルの内容を処理する際に、HTTPリクエストのクエリパラメータ `m` の値をチェックし、その値が `"text"` であれば、特別な処理を行う点にあります。

変更が加えられたのは `src/cmd/godoc/godoc.go` ファイル内の `serveTextFile` 関数です。この関数は、`godoc` のWebインターフェースで個別のソースファイルを表示する際に呼び出されます。

元の実装では、`serveTextFile` 関数は常にファイルの内容をHTMLの `<pre>` タグで囲み、Goのコードであればシンタックスハイライトを適用するなどして整形していました。

今回の変更では、以下のロジックが追加されました。

1.  **`htmlpkg` パッケージのインポート**: HTMLエスケープ処理のために `html` パッケージが `htmlpkg` というエイリアスでインポートされています。これは、既存の `html` という変数名との衝突を避けるためと考えられます。
2.  **`m=text` パラメータのチェック**: `r.FormValue("m") == "text"` という条件式が追加されました。`r` は `*http.Request` 型のオブジェクトで、`FormValue` メソッドは指定されたキー(ここでは `"m"`)に対応するクエリパラメータの値を取得します。
3.  **プレーンテキスト表示の実行**: もし `m` パラメータの値が `"text"` であれば、`serveText(w, src)` が呼び出されます。`serveText` 関数は、ファイルの内容(`src`)をそのままHTTPレスポンスライター `w` に書き込むことで、プレーンテキストとして出力します。そして、`return` ステートメントにより、それ以降のHTML整形処理はスキップされます。
4.  **プレーンテキスト表示へのリンク追加**: 通常のHTML表示の場合(`m=text` でない場合)には、生成されるHTML出力の最後に、プレーンテキスト表示へのリンクが追加されます。具体的には、`<p><a href="/%s?m=text">View as plain text</a></p>` というHTMLスニペットが追加され、`%s` の部分には現在のファイルの相対パスが `htmlpkg.EscapeString` でエスケープされて挿入されます。これにより、ユーザーはHTML表示からワンクリックでプレーンテキスト表示に切り替えることができるようになります。

この変更により、`godoc` はHTTPリクエストの `m=text` パラメータを適切に解釈し、ファイルの内容を要求された形式で提供できるようになりました。

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

```diff
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -15,6 +15,7 @@ import (
 	"go/format"
 	"go/printer"
 	"go/token"
+	htmlpkg "html"
 	"io"
 	"io/ioutil"
 	"log"
@@ -681,10 +682,16 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit
 		return
 	}
 
+	if r.FormValue("m") == "text" {
+		serveText(w, src)
+		return
+	}
+
 	var buf bytes.Buffer
 	buf.WriteString("<pre>")
 	FormatText(&buf, src, 1, pathpkg.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))\n 	buf.WriteString("</pre>")
+	fmt.Fprintf(&buf, `<p><a href="/%s?m=text">View as plain text</a></p>`, htmlpkg.EscapeString(relpath))\n 
 	servePage(w, Page{\n 		Title:    title + " " + relpath,

コアとなるコードの解説

このコミットは、src/cmd/godoc/godoc.go ファイル内の serveTextFile 関数に焦点を当てています。

  1. import htmlpkg "html" の追加:

    • html パッケージは、HTMLテキストのエスケープ処理を提供します。ここでは、既存の変数名との衝突を避けるため、htmlpkg というエイリアスでインポートされています。これは、後述する「View as plain text」リンクのURLを安全に生成するために必要です。
  2. if r.FormValue("m") == "text" { ... } ブロックの追加:

    • r*http.Request 型の変数で、現在のHTTPリクエストを表します。
    • r.FormValue("m") は、HTTPリクエストのURLクエリパラメータから m というキーの値を取得します。例えば、http://example.com/file.go?m=text というURLであれば、"text" が返されます。
    • この条件式は、もし m パラメータの値が "text" であれば、以下の処理を実行することを示しています。
    • serveText(w, src): serveText 関数は、src(ファイルのバイト配列内容)をHTTPレスポンスライター w に直接書き込みます。これにより、ファイルの内容がHTML整形されずにプレーンテキストとしてクライアントに送信されます。
    • return: serveText が呼び出された後、関数はここで終了し、それ以降のHTML整形やページ生成のロジックは実行されません。
  3. fmt.Fprintf(&buf,

    View as plain text

    , htmlpkg.EscapeString(relpath)) の追加:

    • この行は、if r.FormValue("m") == "text" の条件が偽(つまり、m=text パラメータがないか、値が "text" ではない場合)の場合に実行されます。
    • bufbytes.Buffer 型の変数で、HTML形式のファイル内容が格納されています。
    • fmt.Fprintf は、指定されたフォーマット文字列と引数を使って buf に文字列を書き込みます。
    • 追加されるHTMLスニペットは、<p><a href="/%s?m=text">View as plain text</a></p> です。これは、「View as plain text」というテキストを持つハイパーリンクを生成します。
    • %s の部分には、htmlpkg.EscapeString(relpath) の結果が挿入されます。relpath は現在のファイルの相対パス(例: src/pkg/time/time.go)です。htmlpkg.EscapeString は、URLに含める際に特殊文字が問題を起こさないようにエスケープ処理を行います。
    • このリンクをクリックすると、現在のファイルが ?m=text パラメータ付きで再度リクエストされ、プレーンテキスト形式で表示されるようになります。

これらの変更により、godocm=text パラメータの有無に応じて、ファイルの表示形式を動的に切り替えることができるようになりました。

関連リンク

参考にした情報源リンク

  • コミットメッセージと差分情報 (./commit_data/14878.txt)
  • Go言語の公式ドキュメントおよび godoc の挙動に関する一般的な知識
  • HTTPプロトコルとURLクエリパラメータに関する一般的な知識
  • Go言語の net/http パッケージおよび html パッケージの基本的な使用法