Go 1.11 と Go 1.12 以降の違い

Go 1.12 以降のランタイムに移行すると、最新の言語機能を使用するだけでなく、慣用的なコードでより移植性の高いアプリを構築できます。

App Engine Go 1.12 以降のランタイムにおける変更点

Go 1.12+ 以降のランタイムへの移行を検討している場合は、App Engine スタンダード環境の Go 1.12 と以前のランタイムとの次の違いに注意してください。

  • ランタイム移行の労力と複雑さを軽減するため、App Engine スタンダード環境では Go 1.12 以降のランタイムで多くのレガシー バンドル サービスと API にアクセスできます(Memcache など)。Go 1.12 以降のアプリは、Go 向けの App Engine SDK を介してバンドル サービスの API を呼び出すことができ、Go 1.11 ランタイムとほぼ同じ機能にアクセスできます。

    レガシー バンドル サービスと同様の機能を提供する Google Cloud プロダクトを使用することもできます。これらの Google Cloud プロダクトでは、慣用的な Go 用 Cloud クライアント ライブラリを使用できます。Google Cloud で独立したプロダクトとして使用できないバンドル サービス(画像処理、検索、メッセージングなど)の場合は、サードパーティ プロバイダまたはその他の回避策を使用できます。

    バンドルされていないサービスへの移行については、バンドル サービスからの移行をご覧ください。

  • app.yaml 構成ファイルの一部の要素の動作が変更されました。詳細については、app.yaml ファイルの変更点をご覧ください。

  • Go 1.12 以降のランタイムのロギングは、Cloud Logging のロギングの標準に従っています。Go 1.12 以降のランタイムでは、アプリログがリクエストログにバンドルされなくなり、異なるレコードになります。Go 1.12 以降のランタイムでのログの読み取りと書き込みについては、ロギングガイドをご覧ください。

app.yaml ファイルの変更点

app.yaml 構成ファイルの一部の要素の動作が変更されました。

要素 変更タイプ 説明
app_engine_apis Go 1.12 以降のみ Go 1.12 以降用のレガシー バンドル サービスにアクセスする場合は、true に設定する必要があります。
login app_engine_apistrue の場合にサポート Go 1.12 以降用のレガシー バンドル サービスを使用していない場合は、別の方法でユーザーの認証を行います。
runtime 変更 runtime 要素を変更して、Go 1.12 以降を指定します。

詳細については、app.yaml リファレンスをご覧ください。

main パッケージを作成する

サービスのソースファイルのうち少なくとも 1 つpackage main ステートメントを含める必要があります。または、サービスが google.golang.org/appengine パッケージを使用している場合は、appengine.Main() の呼び出しを含めます。

main パッケージを記述する

サービスに main パッケージがない場合は、package main ステートメントを追加し、main() 関数を記述します。少なくとも、次の main() 関数が必要です。

  • PORT 環境変数を読み込み、http.ListenAndServe() 関数を呼び出す。

    port := os.Getenv("PORT")
    if port == "" {
    	port = "8080"
    	log.Printf("Defaulting to port %s", port)
    }
    
    log.Printf("Listening on port %s", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
    	log.Fatal(err)
    }

HTTP ハンドラを登録する

HTTP ハンドラを登録するには、次のいずれかの方法を選択します。

  • 推奨される方法は、すべての http.HandleFunc() 呼び出しをパッケージから main パッケージの main() 関数に手動で移動する方法です。
  • アプリケーションのパッケージを main パッケージにインポートし、各 init() 関数(http.HandleFunc() への呼び出しを含む)が起動時に実行されるようにする方法もあります。

    次の bash スクリプトを使用すると、http.HandleFunc() 呼び出しを使用するすべてのパッケージを検索して、出力を main パッケージの import ブロックにコピーできます。

    gp=$(go env GOPATH) && p=$(pwd) && pkg=${p#"$gp/src/"} && find . -name "*.go" | xargs grep "http.HandleFunc" --files-with-matches | grep -v vendor/ | grep -v '/main.go' | sed "s#\./\(.*\)/[^/]\+\.go#\t_ \"$pkg/\1\"#" | sort | uniq
    

ファイルの構造化

Go では、パッケージごとにディレクトリを作成する必要があります。プロジェクトの app.yaml ファイルで main: を使用して、main パッケージの場所について App Engine に通知できます。たとえば、アプリのファイル構造が次のようになっているとします。

myapp/
├── app.yaml
├── foo.go
├── bar.go
└── web/
    └── main.go

app.yaml ファイルは次のようになります。

main: ./web # Relative filepath to the directory containing your main package.

main フラグの詳細については、app.yaml リファレンスをご覧ください。

GOPATH へのファイルの移動

次のコマンドを使用して、GOPATH を見つけます。

go env GOPATH

関連するすべてのファイルを移動し、GOPATH にインポートします。import ./guestbook のような間接的なインポートを行う場合は、完全なパス import github.com/example/myapp/guestbook を使用するようにインポートを更新します。