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

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

このコミットは、Go言語の初期のコミットの一つであり、src/lib/http/triv.go ファイルに新しい機能を追加しています。具体的には、HTTPサーバーのデモンストレーション用ファイルである triv.go に、コマンドライン引数とフラグの情報をHTTP経由で表示する機能が追加されました。これにより、Goの flag パッケージと sys.Args (現在の os.Args) の基本的な使用方法をHTTPサービスとして確認できるようになっています。

コミット

commit 03d6909ff74d9793b98f587717d5dbd76a4589d5
Author: Rob Pike <r@golang.org>
Date:   Tue Feb 17 19:35:01 2009 -0800

    more fun with triv.go: flags and arguments
    
    R=rsc
    DELTA=23  (23 added, 0 deleted, 0 changed)
    OCL=25088
    CL=25134

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

https://github.com/golang/go/commit/03d6909ff74d9793b98f587717d5dbd76a4589d5

元コミット内容

    more fun with triv.go: flags and arguments
    
    R=rsc
    DELTA=23  (23 added, 0 deleted, 0 changed)
    OCL=25088
    CL=25134

このコミットメッセージは非常に簡潔で、「triv.go でフラグと引数をもっと楽しく」という意図が示されています。これは、triv.go がGo言語の初期段階におけるHTTPサーバーの機能テストやデモンストレーションに使われていたことを示唆しています。

変更の背景

このコミットが行われた2009年2月は、Go言語がまだ一般に公開される前の開発初期段階でした。Go言語の設計思想の一つに、シンプルさと実用性があります。コマンドライン引数とフラグの処理は、多くのCLIツールやサーバーアプリケーションにとって基本的な機能です。

triv.go は、Goの標準ライブラリである net/http パッケージの機能を試すための「おもちゃ」のようなファイルだったと考えられます。このコミットの背景には、Go言語の flag パッケージ(コマンドラインフラグの解析)と sys.Args (現在の os.Args、コマンドライン引数へのアクセス) の基本的な動作を、HTTPサーバーという形で視覚的に確認できるようにするという目的があったと推測されます。これにより、開発者はGoプログラムがどのようにコマンドライン引数やフラグを処理するかを、Webブラウザを通じて簡単に検証できるようになりました。

前提知識の解説

Go言語の初期開発と標準ライブラリ

Go言語は、GoogleでRob Pike、Ken Thompson、Robert Griesemerによって設計され、2009年11月に一般公開されました。このコミットは公開前の開発段階のものであり、当時のGo言語のAPIやパッケージ構成は現在とは異なる部分があります。特に、sys パッケージは後に os パッケージに統合されました。

net/http パッケージ

Go言語の net/http パッケージは、HTTPクライアントとサーバーを実装するための強力な機能を提供します。このパッケージを使用することで、Webサーバーを簡単に構築し、HTTPリクエストを処理することができます。

  • http.Handle(pattern string, handler Handler): 指定されたパターン(URLパス)に対して、http.Handler インターフェースを実装するハンドラを登録します。
  • http.HandlerFunc(f func(ResponseWriter, *Request)): 関数を http.Handler インターフェースに適合させるためのアダプターです。これにより、通常の関数をHTTPハンドラとして登録できます。
  • http.ListenAndServe(addr string, handler Handler): 指定されたアドレスでHTTPサーバーを起動し、リクエストを待ち受けます。handlernil の場合、http.DefaultServeMux が使用されます。

flag パッケージ

Go言語の flag パッケージは、コマンドラインフラグ(例: -port=8080--verbose)を解析するための機能を提供します。

  • flag.Bool(name string, value bool, usage string) *bool: 真偽値のフラグを定義します。
  • flag.Parse(): コマンドライン引数を解析し、定義されたフラグに値を設定します。
  • flag.VisitAll(fn func(*Flag)): 定義されているすべてのフラグに対して、指定された関数 fn を呼び出します。これにより、すべてのフラグの名前、値、デフォルト値などを列挙できます。
  • flag.Flag 構造体: 個々のフラグの情報を保持する構造体で、Name (フラグ名)、Value (現在の値)、DefValue (デフォルト値) などのフィールドを持ちます。

sys.Args (現在の os.Args)

Go言語のプログラムが実行される際に渡されるコマンドライン引数は、os パッケージの os.Args 変数を通じてアクセスできます。これは文字列のスライス([]string)であり、最初の要素 (os.Args[0]) は実行されるプログラムのパスです。このコミット当時は sys.Args という名前でしたが、機能は同じです。

技術的詳細

このコミットは、triv.go という既存のHTTPサーバーのデモンストレーションファイルに、以下の2つの新しいHTTPハンドラを追加しています。

  1. /flags/ エンドポイント (FlagServer 関数):

    • このハンドラは、Goプログラムに定義されているすべてのコマンドラインフラグの情報を表示します。
    • flag.Bool("boolean", true, "another flag for testing") を使って、booleanflag という名前の真偽値フラグを定義しています。デフォルト値は true です。
    • flag.VisitAll 関数を使用して、登録されているすべてのフラグをイテレートします。
    • 各フラグについて、現在の値がデフォルト値と異なる場合は、その旨を明示して表示します。これにより、ユーザーがコマンドラインでフラグの値を変更した場合に、その変更が反映されていることを確認できます。
    • HTTPレスポンスの Content-Type ヘッダを text/plain; charset=utf-8 に設定し、プレーンテキストとして表示されるようにしています。
  2. /args/ エンドポイント (ArgServer 関数):

    • このハンドラは、Goプログラムが起動された際に渡されたすべてのコマンドライン引数を表示します。
    • sys.Args (現在の os.Args) をループで処理し、各引数をスペース区切りでHTTPレスポンスとして出力します。
    • これにより、プログラムがどのような引数で起動されたかをWebブラウザから確認できます。

これらの機能は、Go言語の flag パッケージと sys.Args の基本的な動作を、HTTPサーバーという形で「可視化」する役割を果たしています。開発者は、triv.go を実行し、Webブラウザで /flags//args/ にアクセスすることで、コマンドライン引数やフラグの処理がどのように行われるかを簡単にテスト・確認できるようになります。

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

--- a/src/lib/http/triv.go
+++ b/src/lib/http/triv.go
@@ -45,6 +45,27 @@ func FileServer(c *http.Conn, req *http.Request) {
 	fmt.Fprintf(c, "[%d bytes]\n", n);
 }
 
+// simple flag server
+var booleanflag = flag.Bool("boolean", true, "another flag for testing")
+func FlagServer(c *http.Conn, req *http.Request) {
+	c.SetHeader("content-type", "text/plain; charset=utf-8");
+	fmt.Fprint(c, "Flags:\n");
+	flag.VisitAll(func (f *flag.Flag) {
+		if f.Value.String() != f.DefValue {
+			fmt.Fprintf(c, "%s = %s [default = %s]\n", f.Name, f.Value.String(), f.DefValue);
+		} else {
+			fmt.Fprintf(c, "%s = %s\n", f.Name, f.Value.String());
+		}
+	});
+}
+
+// simple argument server
+func ArgServer(c *http.Conn, req *http.Request) {
+	for i, s := range sys.Args {
+		fmt.Fprint(c, s, " ");
+	}
+}
+
 // a channel (just for the fun of it)
 type Chan chan int
 
@@ -66,6 +87,8 @@ func main() {
 	flag.Parse();
 	http.Handle("/counter", new(Counter));
 	http.Handle("/go/", http.HandlerFunc(FileServer));
+	http.Handle("/flags/", http.HandlerFunc(FlagServer));
+	http.Handle("/args/", http.HandlerFunc(ArgServer));
 	http.Handle("/go/hello", http.HandlerFunc(HelloServer));
 	http.Handle("/chan", ChanCreate());
 	err := http.ListenAndServe(":12345", nil);

コアとなるコードの解説

var booleanflag = flag.Bool("boolean", true, "another flag for testing")

  • flag.Bool は、コマンドラインフラグを定義するための関数です。
  • "boolean" はフラグの名前です。コマンドラインで -boolean または --boolean として指定されます。
  • true はこのフラグのデフォルト値です。
  • "another flag for testing" はフラグの簡単な説明(usage message)です。
  • この行により、booleanflag という名前の *bool 型の変数が宣言され、プログラム内でこのフラグの値にアクセスできるようになります。

func FlagServer(c *http.Conn, req *http.Request)

  • この関数は /flags/ パスへのHTTPリクエストを処理します。
  • c.SetHeader("content-type", "text/plain; charset=utf-8") は、レスポンスがプレーンテキストであることをブラウザに伝えます。
  • fmt.Fprint(c, "Flags:\n") は、レスポンスの冒頭に "Flags:" という見出しを出力します。
  • flag.VisitAll(func (f *flag.Flag) { ... }) は、プログラム内で定義されているすべてのフラグを列挙し、それぞれのフラグに対して匿名関数を実行します。
    • 匿名関数内では、f.Value.String() でフラグの現在の値を取得し、f.DefValue でデフォルト値を取得します。
    • if f.Value.String() != f.DefValue の条件により、現在の値がデフォルト値から変更されている場合に、その旨を [default = %s] の形式で明示的に表示します。これにより、ユーザーがコマンドラインで指定した値が正しく反映されているかを確認できます。

func ArgServer(c *http.Conn, req *http.Request)

  • この関数は /args/ パスへのHTTPリクエストを処理します。
  • for i, s := range sys.Args は、sys.Args (現在の os.Args) の各要素(コマンドライン引数)をループで処理します。
  • fmt.Fprint(c, s, " ") は、各引数をスペース区切りでHTTPレスポンスに出力します。これにより、プログラムがどのようなコマンドライン引数で起動されたかをWebブラウザから確認できます。

http.Handle("/flags/", http.HandlerFunc(FlagServer));

http.Handle("/args/", http.HandlerFunc(ArgServer));

  • main 関数内で、新しく定義された FlagServerArgServer 関数が、それぞれ /flags//args/ というURLパスにHTTPハンドラとして登録されています。
  • http.HandlerFunc は、通常の関数を http.Handler インターフェースに適合させるためのアダプターです。

これらの変更により、triv.go を実行し、Webブラウザで http://localhost:12345/flags/http://localhost:12345/args/ にアクセスすることで、Goプログラムのコマンドライン引数とフラグの処理状況をリアルタイムで確認できるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (現在のバージョン): https://go.dev/doc/
  • Go言語の初期のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
  • Go言語の sys パッケージに関する情報 (歴史的経緯): https://go.dev/doc/go1.1#sys (Go 1.1のリリースノートで sys パッケージが os パッケージに統合されたことが言及されています)
  • Go言語の flag パッケージの基本的な使い方に関するチュートリアルやブログ記事 (一般的な知識として)
  • Go言語の net/http パッケージの基本的な使い方に関するチュートリアルやブログ記事 (一般的な知識として)
  • Rob PikeのGo言語に関する講演や記事 (Go言語の設計思想を理解するため)
  • Go言語の初期のソースコードを直接参照し、当時の文脈を理解するための情報# [インデックス 1695] ファイルの概要

このコミットは、Go言語の初期のコミットの一つであり、src/lib/http/triv.go ファイルに新しい機能を追加しています。具体的には、HTTPサーバーのデモンストレーション用ファイルである triv.go に、コマンドライン引数とフラグの情報をHTTP経由で表示する機能が追加されました。これにより、Goの flag パッケージと sys.Args (現在の os.Args) の基本的な使用方法をHTTPサービスとして確認できるようになっています。

コミット

commit 03d6909ff74d9793b98f587717d5dbd76a4589d5
Author: Rob Pike <r@golang.org>
Date:   Tue Feb 17 19:35:01 2009 -0800

    more fun with triv.go: flags and arguments
    
    R=rsc
    DELTA=23  (23 added, 0 deleted, 0 changed)
    OCL=25088
    CL=25134

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

https://github.com/golang/go/commit/03d6909ff74d9793b98f587717d5dbd76a4589d5

元コミット内容

    more fun with triv.go: flags and arguments
    
    R=rsc
    DELTA=23  (23 added, 0 deleted, 0 changed)
    OCL=25088
    CL=25134

このコミットメッセージは非常に簡潔で、「triv.go でフラグと引数をもっと楽しく」という意図が示されています。これは、triv.go がGo言語の初期段階におけるHTTPサーバーの機能テストやデモンストレーションに使われていたことを示唆しています。

変更の背景

このコミットが行われた2009年2月は、Go言語がまだ一般に公開される前の開発初期段階でした。Go言語の設計思想の一つに、シンプルさと実用性があります。コマンドライン引数とフラグの処理は、多くのCLIツールやサーバーアプリケーションにとって基本的な機能です。

triv.go は、Goの標準ライブラリである net/http パッケージの機能を試すための「おもちゃ」のようなファイルだったと考えられます。このコミットの背景には、Go言語の flag パッケージ(コマンドラインフラグの解析)と sys.Args (現在の os.Args、コマンドライン引数へのアクセス) の基本的な動作を、HTTPサーバーという形で視覚的に確認できるようにするという目的があったと推測されます。これにより、開発者はGoプログラムがどのようにコマンドライン引数やフラグを処理するかを、Webブラウザを通じて簡単に検証できるようになりました。

前提知識の解説

Go言語の初期開発と標準ライブラリ

Go言語は、GoogleでRob Pike、Ken Thompson、Robert Griesemerによって設計され、2009年11月に一般公開されました。このコミットは公開前の開発段階のものであり、当時のGo言語のAPIやパッケージ構成は現在とは異なる部分があります。特に、sys パッケージは後に os パッケージに統合されました。

net/http パッケージ

Go言語の net/http パッケージは、HTTPクライアントとサーバーを実装するための強力な機能を提供します。このパッケージを使用することで、Webサーバーを簡単に構築し、HTTPリクエストを処理することができます。

  • http.Handle(pattern string, handler Handler): 指定されたパターン(URLパス)に対して、http.Handler インターフェースを実装するハンドラを登録します。
  • http.HandlerFunc(f func(ResponseWriter, *Request)): 関数を http.Handler インターフェースに適合させるためのアダプターです。これにより、通常の関数をHTTPハンドラとして登録できます。
  • http.ListenAndServe(addr string, handler Handler): 指定されたアドレスでHTTPサーバーを起動し、リクエストを待ち受けます。handlernil の場合、http.DefaultServeMux が使用されます。

flag パッケージ

Go言語の flag パッケージは、コマンドラインフラグ(例: -port=8080--verbose)を解析するための機能を提供します。

  • flag.Bool(name string, value bool, usage string) *bool: 真偽値のフラグを定義します。
  • flag.Parse(): コマンドライン引数を解析し、定義されたフラグに値を設定します。
  • flag.VisitAll(fn func(*Flag)): 定義されているすべてのフラグに対して、指定された関数 fn を呼び出します。これにより、すべてのフラグの名前、値、デフォルト値などを列挙できます。
  • flag.Flag 構造体: 個々のフラグの情報を保持する構造体で、Name (フラグ名)、Value (現在の値)、DefValue (デフォルト値) などのフィールドを持ちます。

sys.Args (現在の os.Args)

Go言語のプログラムが実行される際に渡されるコマンドライン引数は、os パッケージの os.Args 変数を通じてアクセスできます。これは文字列のスライス([]string)であり、最初の要素 (os.Args[0]) は実行されるプログラムのパスです。このコミット当時は sys.Args という名前でしたが、機能は同じです。

技術的詳細

このコミットは、triv.go という既存のHTTPサーバーのデモンストレーションファイルに、以下の2つの新しいHTTPハンドラを追加しています。

  1. /flags/ エンドポイント (FlagServer 関数):

    • このハンドラは、Goプログラムに定義されているすべてのコマンドラインフラグの情報を表示します。
    • flag.Bool("boolean", true, "another flag for testing") を使って、booleanflag という名前の真偽値フラグを定義しています。デフォルト値は true です。
    • flag.VisitAll 関数を使用して、登録されているすべてのフラグをイテレートします。
    • 各フラグについて、現在の値がデフォルト値と異なる場合は、その旨を明示して表示します。これにより、ユーザーがコマンドラインでフラグの値を変更した場合に、その変更が反映されていることを確認できます。
    • HTTPレスポンスの Content-Type ヘッダを text/plain; charset=utf-8 に設定し、プレーンテキストとして表示されるようにしています。
  2. /args/ エンドポイント (ArgServer 関数):

    • このハンドラは、Goプログラムが起動された際に渡されたすべてのコマンドライン引数を表示します。
    • sys.Args (現在の os.Args) をループで処理し、各引数をスペース区切りでHTTPレスポンスとして出力します。
    • これにより、プログラムがどのような引数で起動されたかをWebブラウザから確認できます。

これらの機能は、Go言語の flag パッケージと sys.Args の基本的な動作を、HTTPサーバーという形で「可視化」する役割を果たしています。開発者は、triv.go を実行し、Webブラウザで /flags//args/ にアクセスすることで、コマンドライン引数やフラグの処理がどのように行われるかを簡単にテスト・確認できるようになります。

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

--- a/src/lib/http/triv.go
+++ b/src/lib/http/triv.go
@@ -45,6 +45,27 @@ func FileServer(c *http.Conn, req *http.Request) {
 	fmt.Fprintf(c, "[%d bytes]\n", n);
 }
 
+// simple flag server
+var booleanflag = flag.Bool("boolean", true, "another flag for testing")
+func FlagServer(c *http.Conn, req *http.Request) {
+	c.SetHeader("content-type", "text/plain; charset=utf-8");
+	fmt.Fprint(c, "Flags:\n");
+	flag.VisitAll(func (f *flag.Flag) {
+		if f.Value.String() != f.DefValue {
+			fmt.Fprintf(c, "%s = %s [default = %s]\n", f.Name, f.Value.String(), f.DefValue);
+		} else {
+			fmt.Fprintf(c, "%s = %s\n", f.Name, f.Value.String());
+		}
+	});
+}
+
+// simple argument server
+func ArgServer(c *http.Conn, req *http.Request) {
+	for i, s := range sys.Args {
+		fmt.Fprint(c, s, " ");
+	}
+}
+
 // a channel (just for the fun of it)
 type Chan chan int
 
@@ -66,6 +87,8 @@ func main() {
 	flag.Parse();
 	http.Handle("/counter", new(Counter));
 	http.Handle("/go/", http.HandlerFunc(FileServer));
+	http.Handle("/flags/", http.HandlerFunc(FlagServer));
+	http.Handle("/args/", http.HandlerFunc(ArgServer));
 	http.Handle("/go/hello", http.HandlerFunc(HelloServer));
 	http.Handle("/chan", ChanCreate());
 	err := http.ListenAndServe(":12345", nil);

コアとなるコードの解説

var booleanflag = flag.Bool("boolean", true, "another flag for testing")

  • flag.Bool は、コマンドラインフラグを定義するための関数です。
  • "boolean" はフラグの名前です。コマンドラインで -boolean または --boolean として指定されます。
  • true はこのフラグのデフォルト値です。
  • "another flag for testing" はフラグの簡単な説明(usage message)です。
  • この行により、booleanflag という名前の *bool 型の変数が宣言され、プログラム内でこのフラグの値にアクセスできるようになります。

func FlagServer(c *http.Conn, req *http.Request)

  • この関数は /flags/ パスへのHTTPリクエストを処理します。
  • c.SetHeader("content-type", "text/plain; charset=utf-8") は、レスポンスがプレーンテキストであることをブラウザに伝えます。
  • fmt.Fprint(c, "Flags:\n") は、レスポンスの冒頭に "Flags:" という見出しを出力します。
  • flag.VisitAll(func (f *flag.Flag) { ... }) は、プログラム内で定義されているすべてのフラグを列挙し、それぞれのフラグに対して匿名関数を実行します。
    • 匿名関数内では、f.Value.String() でフラグの現在の値を取得し、f.DefValue でデフォルト値を取得します。
    • if f.Value.String() != f.DefValue の条件により、現在の値がデフォルト値から変更されている場合に、その旨を [default = %s] の形式で明示的に表示します。これにより、ユーザーがコマンドラインで指定した値が正しく反映されているかを確認できます。

func ArgServer(c *http.Conn, req *http.Request)

  • この関数は /args/ パスへのHTTPリクエストを処理します。
  • for i, s := range sys.Args は、sys.Args (現在の os.Args) の各要素(コマンドライン引数)をループで処理します。
  • fmt.Fprint(c, s, " ") は、各引数をスペース区切りでHTTPレスポンスに出力します。これにより、プログラムがどのようなコマンドライン引数で起動されたかをWebブラウザから確認できます。

http.Handle("/flags/", http.HandlerFunc(FlagServer));

http.Handle("/args/", http.HandlerFunc(ArgServer));

  • main 関数内で、新しく定義された FlagServerArgServer 関数が、それぞれ /flags//args/ というURLパスにHTTPハンドラとして登録されています。
  • http.HandlerFunc は、通常の関数を http.Handler インターフェースに適合させるためのアダプターです。

これらの変更により、triv.go を実行し、Webブラウザで http://localhost:12345/flags/http://localhost:12345/args/ にアクセスすることで、Goプログラムのコマンドライン引数とフラグの処理状況をリアルタイムで確認できるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (現在のバージョン): https://go.dev/doc/
  • Go言語の初期のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
  • Go言語の sys パッケージに関する情報 (歴史的経緯): https://go.dev/doc/go1.1#sys (Go 1.1のリリースノートで sys パッケージが os パッケージに統合されたことが言及されています)
  • Go言語の flag パッケージの基本的な使い方に関するチュートリアルやブログ記事 (一般的な知識として)
  • Go言語の net/http パッケージの基本的な使い方に関するチュートリアルやブログ記事 (一般的な知識として)
  • Rob PikeのGo言語に関する講演や記事 (Go言語の設計思想を理解するため)
  • Go言語の初期のソースコードを直接参照し、当時の文脈を理解するための情報