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

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

このコミットは、Go言語のgoコマンドにおけるリモートパッケージのインポートパス解決メカニズム、特にgo-importメタタグによる発見方法に関するドキュメントの更新です。src/cmd/go/doc.gosrc/cmd/go/help.goの2つのファイルが変更されており、いずれもgo help remoteコマンドで表示されるヘルプドキュメントの内容を拡充しています。

コミット

commit 312ff5b58eea06f2dabb9ba3d28e50d12c64c7d1
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Thu Mar 8 11:31:52 2012 -0800

    cmd/go: document import path meta tag discovery in go help remote
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/5787059

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

https://github.com/golang/go/commit/312ff5b58eea06f2dabb9ba3d28e50d12c64c7d1

元コミット内容

cmd/go: go help remoteにおけるインポートパスのメタタグ発見に関するドキュメント化

変更の背景

Go言語のgo getコマンドは、指定されたインポートパスに基づいてリモートリポジトリからパッケージをダウンロードする機能を提供します。初期のgo getは、GitHubやLaunchpadなどの特定のコードホスティングサイトに対しては特別な構文(例: github.com/user/repo)を認識していました。しかし、それ以外の任意のサーバーでホストされているコードをgo getで取得する場合、ユーザーはインポートパスに直接バージョン管理システム(VCS)のタイプ(例: git.example.org/repo)を含める必要がありました。

このコミットの背景には、より柔軟なインポートパス解決メカニズムの導入があります。具体的には、Goパッケージが任意のHTTP(S)サーバーでホストされている場合でも、そのサーバーが提供するHTMLドキュメント内の特定の<meta>タグ(go-importメタタグ)をgo getが読み取ることで、実際のVCSリポジトリの場所を動的に発見できるようにする機能が実装されました。

この機能は、Goパッケージの配布と利用をより容易にし、特定のホスティングプロバイダーに依存しないエコシステムを構築するために非常に重要です。このコミットは、この新しい(または既存の、しかし十分に文書化されていなかった)メカニズムを公式ドキュメントに明記し、ユーザーがこの強力な機能を利用できるようにすることを目的としています。これにより、ユーザーはカスタムドメインをGoパッケージのインポートパスとして使用できるようになり、ブランドの一貫性やパッケージの可搬性が向上します。

前提知識の解説

このコミットを理解するためには、以下のGo言語およびWeb技術に関する基本的な知識が必要です。

  1. Go Modulesとgo get:

    • go get: Go言語のコマンドラインツールの一つで、リモートリポジトリからGoパッケージとその依存関係をダウンロードし、ローカルのGOPATH(またはGo Modulesが有効な場合はモジュールキャッシュ)に配置するために使用されます。
    • インポートパス: Go言語のソースコード内でパッケージを識別するために使用される文字列です。例えば、import "fmt"は標準ライブラリのfmtパッケージをインポートし、import "github.com/gin-gonic/gin"はGitHub上のginパッケージをインポートします。
    • GOPATH: Go 1.11以前のGoプロジェクトのワークスペースを定義する環境変数です。ソースコード、コンパイル済みバイナリ、パッケージキャッシュなどがこのパスの下に配置されます。Go Modulesの導入により、GOPATHの役割は縮小されましたが、go getの動作を理解する上で依然として重要です。
  2. バージョン管理システム (VCS):

    • Git, Mercurial (hg), Subversion (svn) など、ソースコードの変更履歴を管理するためのシステムです。go getはこれらのVCSクライアントを使用してリモートリポジトリからコードを取得します。
  3. HTML <meta> タグ:

    • HTMLドキュメントの<head>セクションに配置される要素で、ページに関するメタデータ(データに関するデータ)を提供します。通常、ブラウザには表示されませんが、検索エンジンや他のWebサービスがページの内容を理解するために使用します。
    • name属性とcontent属性を持つことが一般的です。例えば、<meta name="description" content="これは私のウェブサイトです">はページの簡単な説明を提供します。
  4. HTTP(S)リクエストとクエリパラメータ:

    • Webブラウザやgo getのようなクライアントは、HTTP(S)プロトコルを使用してWebサーバーにリクエストを送信し、リソース(HTMLページ、画像など)を取得します。
    • クエリパラメータ: URLの末尾に?に続いて追加されるキーと値のペアのリストです。例えば、https://example.com/search?q=golang&lang=enでは、q=golanglang=enがクエリパラメータです。サーバーはこれらのパラメータを使用して、返すコンテンツを動的に生成したり、特定の動作を実行したりします。

これらの知識を前提として、go getがどのようにWebサーバーと連携してGoパッケージのソースコードを見つけるのかを理解することができます。

技術的詳細

このコミットで文書化されているgo-importメタタグによるインポートパスの発見メカニズムは、Go言語のgo getコマンドが、既知のコードホスティングサイト(GitHubなど)以外の任意のWebサーバーからパッケージを取得できるようにするための重要な機能です。

メカニズムの詳細は以下の通りです。

  1. インポートパスの解析:

    • ユーザーがgo get example.org/pkg/fooのようなコマンドを実行すると、goツールはまずexample.orgが既知のコードホスティングサイトであるか、またはインポートパスにVCSタイプ(例: git.example.org/repo)が含まれているかをチェックします。
    • もしこれらに該当しない場合、goツールは動的な発見メカニズムを試みます。
  2. HTTP(S)リクエストの送信:

    • goツールは、インポートパスに対応するURLに対してHTTP(S)リクエストを送信します。この際、特別なクエリパラメータ?go-get=1が付加されます。
    • 優先的にHTTPSが試行され、失敗した場合はHTTPがフォールバックとして試行されます。
    • 例: https://example.org/pkg/foo?go-get=1 (優先) または http://example.org/pkg/foo?go-get=1 (フォールバック)
  3. <meta name="go-import" ...> タグの検索:

    • goツールは、取得したHTMLドキュメントの<head>セクション内から、name="go-import"を持つ<meta>タグを探します。

    • このメタタグのcontent属性は、以下の3つのスペース区切りの値を持つ必要があります。

      • import-prefix: リポジトリのルートに対応するインポートパスです。これは、go getでフェッチしようとしているパッケージのインポートパスのプレフィックスであるか、完全に一致する必要があります。
      • vcs: 使用されているバージョン管理システムのタイプ(例: git, hg, svnなど)。
      • repo-root: VCSリポジトリの実際のルートURLです。これにはスキーム(https://など)が含まれ、.vcsのようなVCSタイプを示す修飾子は含まれません。
    • 例: <meta name="go-import" content="example.org git https://code.org/r/p/exproj">

  4. プレフィックスの検証 (必要に応じて):

    • もしimport-prefixgo getで指定されたインポートパスと完全に一致しない場合(つまり、プレフィックスである場合)、goツールはimport-prefixに対応するURL(例: https://example.org/?go-get=1)に対してもHTTP(S)リクエストを送信し、同じgo-importメタタグが存在するかどうかを検証します。これは、悪意のあるリダイレクトや不正なメタタグの挿入を防ぐためのセキュリティ対策です。
  5. リポジトリのクローン:

    • メタタグが正常に発見・検証されると、goツールは指定されたvcsタイプとrepo-rootを使用して、実際のVCSリポジトリ(例: https://code.org/r/p/exproj)をGOPATH/src/import-prefix(またはGo Modulesのキャッシュディレクトリ)にクローンします。

このメカニズムにより、example.org/pkg/fooのようなカスタムドメインのインポートパスが、実際にはhttps://code.org/r/p/exprojのような別の場所にあるGitリポジトリに対応していることをgo getが透過的に解決できるようになります。これは、Goパッケージの配布において非常に強力な柔軟性を提供します。

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

このコミットによるコードの変更は、Goコマンドのドキュメントファイルに限定されています。

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

    • Goコマンドの全体的なドキュメントを生成するためのソースファイルです。
    • 変更点: go help remoteコマンドで表示されるリモートインポートパスに関する説明に、go-importメタタグによる動的発見メカニズムの詳細が追加されました。具体的には、メタタグの形式、各フィールドの意味、および具体的な例が記述されています。
  2. src/cmd/go/help.go:

    • Goコマンドのヘルプメッセージを生成するためのソースファイルです。
    • 変更点: src/cmd/go/doc.goと同様に、go help remoteの出力にgo-importメタタグに関する説明が追加されました。このファイルは、doc.goの内容をヘルプメッセージとして整形して出力する役割を担っています。

両ファイルでの変更はほぼ同一であり、既存の「他のサーバーでホストされているコード」に関する説明に、メタタグによる発見方法の記述が追記されています。

コアとなるコードの解説

変更されたコードは、Go言語のソースコードではなく、Goコマンドのドキュメント(ヘルプメッセージ)を構成するテキストです。したがって、Goプログラムの動作そのものを変更するものではなく、ユーザーに対する情報提供を改善するものです。

追加されたドキュメントの主要なポイントは以下の通りです。

  • 動的発見の導入:

    --- a/src/cmd/go/doc.go
    +++ b/src/cmd/go/doc.go
    @@ -564,7 +564,12 @@ A few common code hosting sites have special syntax:
     		import "launchpad.net/~user/project/branch/sub/directory"
     
     -For code hosted on other servers, an import path of the form
    +For code hosted on other servers, import paths may either be qualified
    +with the version control type, or the go tool can dynamically fetch
    +the import path over https/http and discover where the code resides
    +from a <meta> tag in the HTML.
    +
    +To declare the code location, an import path of the form
    

    この変更により、「他のサーバーでホストされているコード」のインポートパスが、VCSタイプで修飾されるだけでなく、HTTP(S)経由で<meta>タグを動的にフェッチして発見できるようになったことが明記されました。

  • go-importメタタグの形式:

    +The meta tag has the form:
    +
    +	<meta name="go-import" content="import-prefix vcs repo-root">
    

    メタタグの正確な構文が示され、content属性がimport-prefixvcsrepo-rootの3つの要素から構成されることが説明されています。

  • 各フィールドの説明:

    • import-prefix: リポジトリルートに対応するインポートパスであり、go getでフェッチされるパッケージのプレフィックスまたは完全一致である必要があること。
    • vcs: バージョン管理システムのタイプ(git, hg, svnなど)。
    • repo-root: VCSリポジトリのルートURL。
  • 動作例:

    +For example,
    +
    +	import "example.org/pkg/foo"
    +
    +will result in the following request(s):
    +
    +	https://example.org/pkg/foo?go-get=1 (preferred)
    +	http://example.org/pkg/foo?go-get=1  (fallback)
    +
    +If that page contains the meta tag
    +
    +	<meta name="go-import" content="example.org git https://code.org/r/p/exproj">
    +
    +the go tool will verify that https://example.org/?go-get=1 contains the
    +same meta tag and then git clone https://code.org/r/p/exproj into
    +GOPATH/src/example.org.
    

    具体的なインポートパスexample.org/pkg/fooがどのように解決され、HTTP(S)リクエストが送信され、メタタグがどのように解釈され、最終的にリポジトリがクローンされるかという一連のプロセスが詳細な例で示されています。特に、プレフィックス検証のための追加のHTTPリクエストについても言及されています。

これらのドキュメントの追加により、Goユーザーはgo getコマンドの強力な機能であるカスタムインポートパス解決メカニズムをより深く理解し、活用できるようになりました。

関連リンク

参考にした情報源リンク

  • このコミットの変更内容 (src/cmd/go/doc.go および src/cmd/go/help.go の差分)
  • Go言語の公式ドキュメント (特にgo help remoteコマンドの出力)
  • Go言語のgo getコマンドとインポートパス解決に関する一般的な知識
  • HTML <meta> タグに関する一般的なWeb標準の知識