This page covers instructions for migrating from the first-generation to the second-generation Go runtimes. To upgrade your second-generation app to use the latest supported version of Go, see Upgrade an existing application.
Go 1.11 has reached end of support on January 30, 2024. Your existing Go 1.11 applications will continue to run and receive traffic. However, App Engine might block re-deployment of applications that use runtimes after their end of support date. We recommend that you migrate to the latest supported runtime of Go by using the guidelines in this page.
Migrating to a supported second-generation Go runtime lets you use up-to-date language features and build apps that are more portable, with idiomatic code.
Changes in the second-generation runtimes
Consider the following differences when upgrading to a supported second-generation Go runtime:
To reduce runtime migration effort and complexity, the App Engine standard environment lets you access many of the legacy bundled services and APIs in the second-generation runtimes, such as Memcache. Your second-generation Go app can call the bundled services APIs through the App Engine SDK for Go, and access most of the same features as on the Go 1.11 runtime.
You also have the option to use Google Cloud products that offer similar features as the legacy bundled services. These Google Cloud products provide idiomatic Cloud Client Libraries for Go. For the bundled services that are not available as separate products in Google Cloud, such as image processing, search, and messaging, you can use third-party providers or other workarounds.
To learn more about migrating to unbundled services, see Migrating from bundled services.
The behavior of some elements in the
app.yaml
configuration file has been modified. For more information, see Changes to theapp.yaml
file.Logging in the second-generation runtime follows the logging standard in Cloud Logging. In the second-generation runtimes, app logs are no longer bundled with the request logs but are separated in different records. To learn more about reading and writing logs in the second-generation runtimes, see the logging guide.
Memory usage differences
Second-generation runtimes see a higher baseline of memory usage compared to first-generation runtimes. This is due to multiple factors, such as different base image versions, and differences in how the two generations calculate memory usage.
Second-generation runtimes calculate instance memory usage as the sum of what an application process uses, and the number of application files dynamically cached in memory. To avoid memory-intensive applications from experiencing instance shutdowns due to exceeding memory limits, upgrade to a larger instance class with more memory.
CPU usage differences
Second-generation runtimes can see a higher baseline of CPU usage upon instance cold-start. Depending on an application's scaling configuration, this might have unintended side effects, such as, a higher instance count than anticipated if an application is configured to scale based on CPU utilization. To avoid this issue, review and test application scaling configurations to ensure the number of instances are acceptable.
Request header differences
First-generation runtimes allow request headers with underscores
(e.g. X-Test-Foo_bar
) to be forwarded to the application. Second-generation
runtimes introduces Nginx into the host architecture. As a result of this
change, second-generation runtimes are configured to automatically remove
headers with underscores (_
). To prevent application issues, avoid using
underscores in application request headers.
Changes to the app.yaml
file
The behavior of some elements in the app.yaml
configuration file has been
modified:
Element | Change type | Description |
---|---|---|
app_engine_apis |
Required for apps using legacy bundled services | Must be set to true if you want to access the
legacy bundled services for the second-generation runtimes.
|
login |
Supported if app_engine_apis is true |
If you are not using the legacy bundled services for the second-generation runtimes, use these alternative methods to authenticate users. |
runtime |
Modified |
Change the runtime element to
specify a second-generation runtime.
|
For more information, see the
app.yaml
reference.
Creating a main
package
Your service must include a package main
statement in at least one source
file. Alternatively, if your service is using the google.golang.org/appengine
package, include a call to appengine.Main()
.
Writing a main package
If your service doesn't already contain a main
package, add the
package main
statement and write a main()
function. At a minimum,
the main()
function should:
Read the
PORT
environment variable and call thehttp.ListenAndServe()
function:
Registering your HTTP handlers
You can register your HTTP handlers by choosing one of the following options:
- The preferred method is to manually move all
http.HandleFunc()
calls from your packages to yourmain()
function in yourmain
package. Alternatively, import your application's packages into your
main
package, ensuring eachinit()
function that contains calls tohttp.HandleFunc()
gets run on startup.You can find all packages which use the
http.HandleFunc()
call with the following bash script, and copy the output into yourmain
package'simport
block: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
Structuring your files
Go requires each package has its own directory. You can tell
App Engine where your main
package is by using main:
in your
project's app.yaml
file. For example, if your app's file structure looked
like this:
myapp/ ├── app.yaml ├── foo.go ├── bar.go └── web/ └── main.go
Your app.yaml
file would have:
main: ./web # Relative filepath to the directory containing your main package.
For more information about the main
flag, see the app.yaml
reference.
Moving files to your GOPATH
Find your GOPATH
by using the following command:
go env GOPATH
Move all relevant files and imports to your GOPATH
. If using relative
imports, such as import ./guestbook
, update your imports to use the full
path: import github.com/example/myapp/guestbook
.