在 main() 函数中,调用 appengine.Main() 而不是 http.ListenAndServe()。这样可确保 user 和 appengine API 可以访问当前请求上下文。
编写 main 软件包
如果您的服务尚不包含 main 软件包,请添加 package main 语句并编写 main() 函数。main() 函数至少应该:
读取 PORT 环境变量并调用 http.ListenAndServe() 函数:
port:=os.Getenv("PORT")ifport==""{port="8080"log.Printf("Defaulting to port %s",port)}log.Printf("Listening on port %s",port)iferr:=http.ListenAndServe(":"+port,nil);err!=nil{log.Fatal(err)}
注册 HTTP 处理程序
您可以通过以下任一方案来注册 HTTP 处理程序:
首选方法是手动将您的软件包中的所有 http.HandleFunc() 调用移入您的 main 软件包中的 main() 函数。
另一种方法是将应用的软件包导入 main 软件包,并确保每个 init() 函数(包含对 http.HandleFunc() 的调用)在启动时运行。
您可以通过以下 bash 脚本找到所有使用 http.HandleFunc() 调用的软件包,并将输出复制到 main 软件包的 import 块中:
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["很难理解","hardToUnderstand","thumb-down"],["信息或示例代码不正确","incorrectInformationOrSampleCode","thumb-down"],["没有我需要的信息/示例","missingTheInformationSamplesINeed","thumb-down"],["翻译问题","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-08-21。"],[[["\u003cp\u003eThis guide provides instructions for migrating applications from first-generation to supported second-generation Go runtimes on App Engine, including changes to \u003ccode\u003eapp.yaml\u003c/code\u003e, memory and CPU usage, and request headers.\u003c/p\u003e\n"],["\u003cp\u003eGo 1.11 reached its end of support on January 30, 2024, and while existing applications will continue to run, redeployment might be blocked; thus, it is recommended to migrate to the latest supported Go runtime.\u003c/p\u003e\n"],["\u003cp\u003eSecond-generation runtimes allow access to many legacy bundled services via the App Engine SDK, but some are not available, requiring the use of alternative Google Cloud products, third-party services, or other workarounds.\u003c/p\u003e\n"],["\u003cp\u003eMigrating to a second-generation Go runtime requires creating a \u003ccode\u003emain\u003c/code\u003e package, and registering your HTTP handlers either by manually moving \u003ccode\u003ehttp.HandleFunc()\u003c/code\u003e calls or importing packages with \u003ccode\u003einit()\u003c/code\u003e functions.\u003c/p\u003e\n"],["\u003cp\u003eUpgrading may involve managing increased baseline memory and CPU usage, avoiding underscores in request headers, and adjusting the \u003ccode\u003eapp.yaml\u003c/code\u003e file's \u003ccode\u003eapp_engine_apis\u003c/code\u003e, \u003ccode\u003elogin\u003c/code\u003e, and \u003ccode\u003eruntime\u003c/code\u003e elements.\u003c/p\u003e\n"]]],[],null,["# Migrate from Go 1.11 to the latest Go runtime\n\nThis page covers instructions for migrating from the\n[first-generation to the second-generation](/appengine/docs/standard/runtimes)\nGo runtimes. To upgrade your second-generation app to use the latest supported\nversion of Go, see [Upgrade an existing application](/appengine/docs/standard/go/upgrade-go-runtime).\n\nGo 1.11 has reached [end of support](/appengine/docs/standard/lifecycle/runtime-lifecycle#end_of_support)\non January 30, 2024. Your existing Go 1.11 applications will continue\nto run and receive traffic. However, App Engine might block re-deployment of applications\nthat use runtimes [after their end of support date](/appengine/docs/standard/lifecycle/support-schedule#go).\nWe recommend that you migrate to the [latest supported runtime](/appengine/docs/standard/lifecycle/support-schedule#go) of Go by using the\nguidelines in this page.\n\nMigrating to a [supported second-generation Go runtime](/appengine/docs/standard/runtimes)\nlets you use up-to-date language\nfeatures and build apps that are more portable, with idiomatic code.\n\nChanges in the second-generation runtimes\n-----------------------------------------\n\nConsider the following differences when upgrading to a [supported](/appengine/docs/standard/lifecycle/support-schedule#go) second-generation Go runtime:\n\n- To reduce runtime migration effort and complexity, the App Engine standard environment lets you\n [access many of the legacy bundled services and APIs in the second-generation\n runtimes](/appengine/docs/standard/go/services/access), such as Memcache.\n Your second-generation Go app can call the bundled services APIs through the\n App Engine SDK for Go, and access most of the same features as on the\n Go 1.11 runtime.\n\n | **Note:** Not all the App Engine bundled services available for Go 1.11 have a corresponding service in the second-generation runtimes. For the full list of available legacy bundled services APIs in the second-generation runtimes, see the [legacy bundled services API references documentation](/appengine/docs/standard/go/services/access).\n\n You also have the option to use Google Cloud products that offer\n similar features as the legacy bundled services. These Google Cloud\n products provide idiomatic [Cloud Client Libraries for Go](https://github.com/googleapis/google-cloud-go).\n For the bundled services that are not available as separate products in\n Google Cloud, such as image processing, search, and messaging, you can\n use third-party providers or other workarounds.\n\n To learn more about migrating to unbundled services, see\n [Migrating from bundled services](/appengine/migration-center/standard/services/migrating-services).\n- The behavior of some elements in the `app.yaml` configuration file has been\n modified. For more information, see [Changes to the `app.yaml` file](#app-yaml).\n\n- Logging in the second-generation runtime follows the logging standard in\n [Cloud Logging](/logging). In the second-generation runtimes,\n app logs are no longer bundled with the request logs but are separated in\n different records. To learn more about reading and writing logs in the\n second-generation runtimes, see the [logging guide](/appengine/docs/standard/writing-application-logs).\n\n### Memory usage differences\n\nSecond-generation runtimes see a higher baseline of memory usage compared\nto first-generation runtimes. This is due to multiple factors, such as different\nbase image versions, and differences in how the two generations calculate memory\nusage.\n\nSecond-generation runtimes calculate instance memory usage as the sum of what an\napplication process uses, and the number of application files dynamically cached\nin memory. To avoid memory-intensive applications from experiencing instance\nshutdowns due to exceeding memory limits, upgrade to a larger\n[instance class](/appengine/docs/standard#instance_classes) with more memory.\n\n### CPU usage differences\n\nSecond-generation runtimes can see a higher baseline of CPU usage upon instance\ncold-start. Depending on an application's scaling configuration, this might have\nunintended side effects, such as, a higher instance count than anticipated if an\napplication is configured to scale based on CPU utilization. To avoid this\nissue, review and test application scaling configurations to ensure the number\nof instances are acceptable.\n\n### Request header differences\n\nFirst-generation runtimes allow request headers with underscores\n(e.g. `X-Test-Foo_bar`) to be forwarded to the application. Second-generation\nruntimes introduces Nginx into the host architecture. As a result of this\nchange, second-generation runtimes are configured to automatically remove\nheaders with underscores (`_`). To prevent application issues, avoid using\nunderscores in application request headers.\n\nChanges to the `app.yaml` file\n------------------------------\n\nThe behavior of some elements in the `app.yaml` configuration file has been\nmodified:\n\nFor more information, see the\n[`app.yaml` reference](/appengine/docs/standard/reference/app-yaml).\n\nCreate a `main` package\n-----------------------\n\nYour service must include a `package main` statement in at least one source\nfile.\n\n### App Engine legacy bundled services\n\nIf your service uses the\n[legacy bundled services\nfor the second-generation runtimes](/appengine/docs/standard/go/services/access):\n\n- Your service must only use v2 (`google.golang.org/appengine/v2`) packages.\n Using the older v1 (`google.golang.org/appengine`) packages causes errors.\n\n- In your `main()` function, call `appengine.Main()` instead of\n `http.ListenAndServe()`. This ensures that the `user` and `appengine`\n APIs have access to current request context.\n\n### Writing a main package\n\nIf your service doesn't already contain a `main` package, add the\n`package main` statement and write a `main()` function. At a **minimum** ,\nthe `main()` function should:\n\n- Read the `PORT` environment variable and call the `http.ListenAndServe()`\n function:\n\n port := os.Getenv(\"PORT\")\n if port == \"\" {\n \tport = \"8080\"\n \tlog.Printf(\"Defaulting to port %s\", port)\n }\n\n log.Printf(\"Listening on port %s\", port)\n if err := http.ListenAndServe(\":\"+port, nil); err != nil {\n \tlog.Fatal(err)\n }\n\n### Registering your HTTP handlers\n\nYou can register your HTTP handlers by choosing **one** of the following\noptions:\n\n- The preferred method is to manually move all `http.HandleFunc()` calls from your packages to your `main()` function in your `main` package.\n- Alternatively, import your application's packages into your `main` package,\n ensuring each `init()` function that contains calls to `http.HandleFunc()`\n gets run on startup.\n\n You can find all packages which use the `http.HandleFunc()` call with the\n following bash script, and copy the output into your `main` package's\n `import` block: \n\n 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\n\nStructuring your files\n----------------------\n\nGo requires each package has its own directory. You can tell\nApp Engine where your `main` package is by using `main:` in your\nproject's `app.yaml` file. For example, if your app's file structure looked\nlike this: \n\n```\nmyapp/\n├── app.yaml\n├── foo.go\n├── bar.go\n└── web/\n └── main.go\n```\n\nYour `app.yaml` file would have: \n\n main: ./web # Relative filepath to the directory containing your main package.\n\nFor more information about the `main` flag, see the [`app.yaml`\nreference](/appengine/docs/standard/go/config/appref#main).\n\nMoving files to your `GOPATH`\n-----------------------------\n\nFind your `GOPATH` by using the following command: \n\n go env GOPATH\n\nMove all relevant files and imports to your `GOPATH`. If using relative\nimports, such as `import ./guestbook`, update your imports to use the full\npath: `import github.com/example/myapp/guestbook`."]]