Go Modulesへの移行

10268 ワード

文書ディレクトリ

  • 概要
  • プロジェクトをGo modules
  • に移行
  • 依存マネージャ
  • を使用
  • 依存マネージャがない
  • モジュールモードでのテスト
  • リリースリリース
  • モジュールパス
  • のインポートと仕様
  • 結論
  • 関連記事
  • 参考文献
  • 概要


    翻訳はGo公式ブログMigrating To Go Modulesから.
    Jean de Klerk 21 August 2019
    この文章はシリーズの第二部分です.
  • Part 1 — Using Go Modules
  • Part 2 — Migrating To Go Modules (this post)
  • Part 3 — Publishing Go Modules
  • Part 4 — Go Modules: v2 and Beyond
  • Part 5 — Keeping Your Modules Compatible

  • Goプロジェクトでは、vendorパッケージの管理に人気のある2つのツールdepとglideがありますが、動作に大きな違いがあり、常によく同時に使用できるわけではありません.一部のプロジェクトでは、GOPATHディレクトリ全体をGitウェアハウスに格納します.他の人はgo getにのみ依存し、GOPATHに新しいバージョンの依存項目をインストールすることを望んでいる.
    GoのモジュールシステムはGo 1.11に導入され、Goコマンドに組み込まれた公式依存管理ソリューションを提供します.この文書では、プロジェクトをモジュールに変換する関連ツールと技術について説明します.
    アイテムがv 2とマークされている場合は注意してください.0.0以降のバージョンではgoが追加されます.modファイルの場合はモジュールパスを更新する必要があります.ユーザーを破壊することなく、後で説明します.

    プロジェクトをGo modulesに移行


    Goモジュールへの移行を開始すると、プロジェクトは次の3つの状態のいずれかになります.
  • 新しいGoプロジェクト
  • は、モジュールを使用して確立されたGoプロジェクト
  • を管理する必要はありません.
  • 依存マネージャを使用しない確立されたGoプロジェクト
  • 1つ目のケースはGo Modulesで紹介されています.本稿では,後者の2つの状況について論じる.

    依存マネージャの使用


    依存管理ツールを使用しているプロジェクトを変換するには、次のコマンドを実行します.
    $ git clone https://github.com/my/project
    [...]
    $ cd project
    $ cat Godeps/Godeps.json
    {
        "ImportPath": "github.com/my/project",
        "GoVersion": "go1.12",
        "GodepVersion": "v80",
        "Deps": [
            {
                "ImportPath": "rsc.io/binaryregexp",
                "Comment": "v0.2.0-1-g545cabd",
                "Rev": "545cabda89ca36b48b8e681a30d9d769a30b3074"
            },
            {
                "ImportPath": "rsc.io/binaryregexp/syntax",
                "Comment": "v0.2.0-1-g545cabd",
                "Rev": "545cabda89ca36b48b8e681a30d9d769a30b3074"
            }
        ]
    }
    $ go mod init github.com/my/project
    go: creating new go.mod: module github.com/my/project
    go: copying requirements from Godeps/Godeps.json
    $ cat go.mod
    module github.com/my/project
    
    go 1.12
    
    require rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
    $
    
    go mod init新しいgoを作成します.modファイルは自動的にGodepsからjson、Gopkg.lockは、他のサポートされているフォーマットから依存項目をインポートすることが多いかもしれません.go mod initパラメータは、モジュールの位置を示すモジュールパスである.go buildgo testを一時停止して運転する好機です.後でgoを修正するかもしれません.modファイルなので、反復的な方法が好きなら、現在のgo.modファイルは、以前の依存説明に最も近い.
    $ go mod tidy
    go: downloading rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
    go: extracting rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
    $ cat go.sum
    rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca h1:FKXXXJ6G2bFoVe7hX3kEX6Izxw5ZKRH57DFBJmHCbkU=
    rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
    $
    
    go mod tidyすべての依存するパケットおよび間接依存するパケットを見つけ、goに追加する.modファイルで、不要な依存パッケージを削除します.直接依存パケットがGo Moduleを有効にしていない場合、間接依存パケットの末尾は注釈// indirectによってマークされる.go.modファイルがバージョンライブラリにコミットされる前に、go.mod tidyを実行することが望ましい.
    コードが正常に構築され、テストされることを確認します.
    $ go build ./...
    $ go test ./...
    [...]
    $
    

    他の依存マネージャは、モジュールではなく単一のパッケージまたはコードウェアハウス全体のレベルで依存項目を指定し、通常、依存項目のgoを識別しないことに注意してください.modファイルで指定した依存項目.したがって、以前とまったく同じパッケージのバージョンは得られず、アップグレードの変更によるリスクがあります.したがって,上記のコマンドに従い,結果の依存項目を監査することが重要である.これを行うには、次の手順に従います.
    $ go list -m all
    go: finding rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
    github.com/my/project
    rsc.io/binaryregexp v0.2.1-0.20190524193500-545cabda89ca
    $
    

    結果バージョンを古い依存管理ファイルと比較して、選択したバージョンが適切であることを確認します.バージョンが望ましくない場合は、go mod why -mおよび/またはgo mod graphを使用して理由を特定し、go getを使用して正しいバージョンにアップグレードまたはダウングレードできます.例:
    $ go mod why -m rsc.io/binaryregexp
    [...]
    $ go mod graph | grep rsc.io/binaryregexp
    [...]
    $ go get rsc.io/[email protected]
    $
    

    依存マネージャなし


    関係管理システムに依存しないGoプロジェクトについては、まずgoを作成する.modファイル:
    $ git clone https://go.googlesource.com/blog
    [...]
    $ cd blog
    $ go mod init golang.org/x/blog
    go: creating new go.mod: module golang.org/x/blog
    $ cat go.mod
    module golang.org/x/blog
    
    go 1.12
    $
    

    以前の依存項目マネージャからのプロファイルがない場合、go mod initはmoduleおよびgoコマンドのみを含むgo.modファイルを作成します.この例では、モジュールパスをgolangに設定する.org/x/blogは、カスタムインポートパスであるためです.ユーザーはこのパスを使用してパッケージをインポートできます.勝手に変更しないように注意する必要があります.
    module命令はモジュールパスを宣言し、go命令はモジュール内のコードGo言語の予想バージョンをコンパイルするために使用される.
    次に、モジュールの依存項目を追加するためにgo mod tidyを実行します.
    $ go mod tidy
    go: finding golang.org/x/website latest
    go: finding gopkg.in/tomb.v2 latest
    go: finding golang.org/x/net latest
    go: finding golang.org/x/tools latest
    go: downloading github.com/gorilla/context v1.1.1
    go: downloading golang.org/x/tools v0.0.0-20190813214729-9dba7caff850
    go: downloading golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
    go: extracting github.com/gorilla/context v1.1.1
    go: extracting golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
    go: downloading gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
    go: extracting gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
    go: extracting golang.org/x/tools v0.0.0-20190813214729-9dba7caff850
    go: downloading golang.org/x/website v0.0.0-20190809153340-86a7442ada7c
    go: extracting golang.org/x/website v0.0.0-20190809153340-86a7442ada7c
    $ cat go.mod
    module golang.org/x/blog
    
    go 1.12
    
    require (
        github.com/gorilla/context v1.1.1
        golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
        golang.org/x/text v0.3.2
        golang.org/x/tools v0.0.0-20190813214729-9dba7caff850
        golang.org/x/website v0.0.0-20190809153340-86a7442ada7c
        gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
    )
    $ cat go.sum
    cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
    cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
    git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
    git.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
    github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
    [...]
    $
    
    go mod tidyはモジュール依存のすべてのパケットと間接依存パケットを追加し、goを生成する.sumファイル.各依存パッケージの特定のバージョンのチェックサムが含まれます.終了時にコードが生成され、テストに合格することを確認します.
    $ go build ./...
    $ go test ./...
    ok  	golang.org/x/blog	0.335s
    ?   	golang.org/x/blog/content/appengine	[no test files]
    ok  	golang.org/x/blog/content/cover	0.040s
    ?   	golang.org/x/blog/content/h2push/server	[no test files]
    ?   	golang.org/x/blog/content/survey2016	[no test files]
    ?   	golang.org/x/blog/content/survey2017	[no test files]
    ?   	golang.org/x/blog/support/racy	[no test files]
    $
    
    go mod tidyに依存が追加されると、モジュールの最新バージョンが追加されることに注意してください.GOPATHに古いバージョンの依存項目が含まれていて、その後突破的な変更が発表された場合は、go mod tidygo build、またはgo testでエラーが発生する可能性があります.このような場合は、go get(例えばgo get github.com/broken/[email protected])を古いバージョンに降格するか、モジュールを各依存項目の最新バージョンと互換性を保つのに時間がかかります.

    モジュールモードでのテスト


    一部のテストでは、Goモジュールに移行した後に調整する必要がある場合があります.
    テストでパッケージディレクトリにファイルを書き込む必要がある場合は、モジュールキャッシュが読み取り専用であるため、パッケージディレクトリがモジュールキャッシュにある場合に失敗する可能性があります.特に、これはgo test allの失敗を招く可能性がある.テスト時に書き込みが必要なファイルを一時ディレクトリにコピーする必要があります.
    テストが相対パス(.../package-in-another-module)に依存して別のパケットのファイルを位置決めおよび読み取り、依存するパケットが別のモジュールにある場合、テストは失敗します.モジュールは、モジュールキャッシュのバージョンサブディレクトリまたはreplaceコマンドで指定したパスに配置されます.もしそうなら、テスト入力をモジュールにコピーするか、テスト入力を元のファイルから埋め込みに変換する必要があります.goソースファイルのデータ.
    テスト中のGoコマンドをGOPATHモードで実行したい場合は、失敗する可能性があります.もしそうなら、テストされたソースファイルディレクトリにgoを追加する必要があるかもしれません.modファイル、またはGO 111 MODULE=OFFを明示的に設定します.
    go env -w GO111MODULE=OFF
    

    リリース


    最後に、モジュールの新しいバージョンをマークしてパブリッシュする必要があります.まだリリースされていない場合は、これはオプションです.しかし、正式なバージョンがない場合、下流ユーザーは偽バージョンを使用する特定のコミットに依存し、サポートが困難になる可能性があります.
    $ git tag v1.2.0
    $ git push origin v1.2.0
    

    新しいgo.modファイルは、モジュールに仕様のインポートパスを定義し、Goの最低バージョン要件を追加します.ユーザーが正しいインポートパスを使用しており、モジュールが中断的に変更されていない場合はgoを追加します.modファイルは後方互換性がありますが、これは重大な変更であり、既知の問題が発生する可能性があります.既存のバージョンタグがある場合は、minor versionを追加する必要があります.バージョンの追加とリリース方法については、Publishing Go Modulesを参照してください.

    モジュールパスのインポートとスペシフィケーション


    各モジュールはgo.modファイルでモジュールパスを宣言します.各参照モジュール内のパケットのインポート文は、モジュールパスをパケットパスの接頭辞として使用する必要があります.ただし、golangのような異なるインポートパスを介してパケットを提供するコードウェアハウスに遭遇する場合がある.org/x/lintとgithub.com/golang/lintはモジュールgoを指す.googlesource.com/lint.コードライブラリに含まれるgo.modファイルは、そのパスがgolangであることを宣言する.org/x/lintなので、このパスだけが有効なモジュールに対応します.
    Go 1.4は、// import comments仕様の導入経路を使用するメカニズムを提供するが、パッケージ作成者は必ずしも提供しない.したがって、モジュールの前に記述されたコードは、モジュールに非仕様のインポートパスを使用する可能性がありますが、一致しないエラーは発生しません.モジュールを使用する場合、インポートパスはモジュール仕様パスと一致する必要があります.そのため、import文を更新する必要があります.たとえば、import “github.com/golang/lint”import “golang.org/x/lint”に変更する必要があります.
    プライマリ・バージョン2以降のGoモジュールでは、モジュールの仕様パスが倉庫パスと異なる場合があります.プライマリ・バージョンが1より高いGoモジュールは、そのモジュールパスにプライマリ・バージョンの接尾辞を含める必要があります.たとえば、バージョンv 2.0.0には、接尾辞/v 2が必要です.ただし、import文は、モジュールに接尾辞がないパッケージを参照する可能性があります.例えば、非モジュールユーザはgithubを用いる.com/russrose/blackfriday/v 2パッケージはバージョンv 2に対応する.0.1はgithubとしてインポートする可能性がある.com/russrose/blackfridayの場合、/v 2接尾辞を含むインポートパスを更新する必要があります.

    結論


    ほとんどのユーザーにとって、Goモジュールへの変換は簡単なプロセスであるべきです.非仕様のインポートパスまたは依存項目の破損した変更のため、たまに問題が発生する可能性があります.以降の記事では、新しいバージョン、v 2以降のバージョン、デバッグ異常のリリース方法について検討します.
    フィードバックを提供し、Go依存管理の将来を支援する場合は、エラーレポートまたは経験レポートを送信します.
    Goモジュールを改善するためのフィードバックと助けに感謝します.

    関連記事

  • Using Go Modules
  • Keeping Your Modules Compatible
  • Go Modules: v2 and Beyond
  • Publishing Go Modules
  • Module Mirror and Checksum Database Launched
  • Go Modules in 2019
  • A Proposal for Package Versioning in Go
  • The cover story
  • The App Engine SDK and workspaces (GOPATH)
  • Organizing Go code

  • 参考文献


    [1]【Goエキスパートプログラミング】go.modファイルのindirectの正確な意味