2 回答
TA贡献1852条经验 获得超1个赞
如果您有一些代码在本地机器和 AppEngine 环境中都可以工作,那么您无需做任何事情。
如果您需要在 AppEngine 上做一些应该或必须做不同的事情,那么您需要检测环境并为不同的环境编写不同的代码。
这种检测和代码选择最容易使用构建约束来完成。您可以在.go文件的开头放置一个特殊的注释行,它可能会或可能不会编译和运行,具体取决于环境。
引用Go 博客:App Engine SDK 和工作区(GOPATH):
App Engine SDK 引入了一个新的构建约束术语:"appengine". 指定的文件
// +build appengine
将由 App Engine SDK 构建并被 go 工具忽略。相反,指定文件
// +build !appengine
App Engine SDK 会忽略它们,而 go 工具会很高兴地构建它们。
例如,您可以有 2 个单独.go的文件,一个用于 AppEngine,一个用于本地(非 AppEngine)环境。在两者中定义相同的函数(具有相同的参数列表),因此无论在哪个环境中构建代码,该函数都会有一个声明。我们将使用这个签名:
func GetURL(url string, r *http.Request) ([]byte, error)
请注意,*http.Request仅 AppEngine 需要第二个参数 ( )(以便能够创建 a Context),因此在本地环境的实现中不使用它(甚至可以是nil)。
一个优雅的解决方案可以利用http.Client在标准环境和 AppEngine 中都可用的类型,并且可以用于执行 HTTP GET 请求。一个http.Client值可以在不同的AppEngine被收购,但一旦我们有一个http.Client值,我们可以继续以同样的方式。所以我们将有一个通用代码来接收一个http.Client并可以完成其余的工作。
示例实现如下所示:
url_local.go:
// +build !appengine
package mypackage
import (
"net/http"
)
func GetURL(url string, r *http.Request) ([]byte, error) {
// Local GetURL implementation
return GetClient(url, &http.Client{})
}
url_gae.go:
// +build appengine
package mypackage
import (
"google.golang.org/appengine"
"google.golang.org/appengine/urlfetch"
"net/http"
)
func GetURL(url string, r *http.Request) ([]byte, error) {
// Appengine GetURL implementation
ctx := appengine.NewContext(r)
c := urlfetch.Client(ctx)
return GetClient(url, c)
}
url_common.go:
// No build constraint: this is common code
package mypackage
import (
"net/http"
)
func GetClient(url string, c *http.Client) ([]byte, error) {
// Implementation for both local and AppEngine
resp, err := c.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
TA贡献1863条经验 获得超2个赞
- 2 回答
- 0 关注
- 227 浏览
添加回答
举报