Notice: Over the next few months, we're reorganizing the App Engine documentation site to make it easier to find content and better align with the rest of Google Cloud products. The same content will be available, but the navigation will now match the rest of the Cloud products. If you have feedback or questions as you navigate the site, click Send Feedback.

Differences between Go 1.11 and Go 1.12+

Migrating to the Go 1.12+ runtime allows you to use up-to-date language features and build apps that are more portable, with idiomatic code.

Changes in the App Engine Go 1.12+ runtime

If you are considering a migration to the Go 1.12+ runtime, you should be aware of the following differences between Go 1.12+ and earlier runtimes on App Engine standard environment:

  • To reduce runtime migration effort and complexity, the App Engine standard environment allows you to access many of the legacy bundled services and APIs in the Go 1.12+ runtime, such as Memcache. Your Go 1.12+ app can call the bundled services APIs through the App Engine SDK for Go, and access most of the same functionality as on the Go 1.11 runtime.

    You also have the option to use Google Cloud products that offer similar functionality 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 the app.yaml file.

  • Logging in the Go 1.12+ runtime follows the logging standard in Cloud Logging. In the Go 1.12+ runtime, 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 Go 1.12+ runtime, see the logging guide.

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 Applicable to Go 1.12+ only Must be set to true if you want to access the legacy bundled services for Go 1.12+.
login Supported if app_engine_apis is true If you are not using the legacy bundled services for Go 1.12+, use these alternative methods to authenticate users.
runtime Modified Change the runtime element to specify Go 1.12+.

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 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 the http.ListenAndServe() function:

    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 {

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 your main() function in your main package.
  • Alternatively, import your application's packages into your main package, ensuring each init() function that contains calls to http.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 your main package's import 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:

├── 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