Go 部落格

App Engine SDK 與工作空間 (GOPATH)

Andrew Gerrand
2013 年 1 月 9 日

簡介

我們釋出 Go 1 時推出了 go 工具,隨附著工作空間的概念。工作空間(由 GOPATH 環境變數指定)是一種組織程式碼的慣例,可簡化提取、建置和安裝 Go 套件。如果您不熟悉工作空間,請在進一步閱讀之前閱讀 這篇文章 或觀看 這個螢幕錄製檔案

直到最近為止,App Engine SDK 中的工具尚未了解工作空間。如果不使用工作空間,「go get」命令無法運作,因此應用程式作者必須手動安裝和更新應用程式相關程式。這是件麻煩的事。

這一切隨著應用程式引擎 SDK 1.7.4 版的推出而有所改變。dev_appserverappcfg 工具現已具備工作區感知能力。在執行本機執行或上傳應用程式時,這些工具現會在 GOPATH 環境變數指定的 Workspace 中搜尋相依性。這表示您可以在建置應用程式引擎應用程式時使用「go get」,並在正常的 Go 程式與應用程式引擎應用程式之間切換,而無須變更您的環境或使用習慣。

例如,假設您想建立一個使用 OAuth 2.0 向遠端服務進行驗證的應用程式。一個適用於 Go 的熱門 OAuth 2.0 函式庫是 oauth2 套件,您可以使用此命令將其安裝到您的 Workspace

go get golang.org/x/oauth2

在撰寫應用程式引擎應用程式時,請如同在一般的 Go 程式中一樣,導入 oauth 套件

import "golang.org/x/oauth2"

接著,無論是使用 dev_appserver 執行您的應用程式,還是使用 appcfg 部署應用程式,這些工具都會在您的 Workspace 中找到 oauth 套件。它會自動運作。

混合的獨立應用程式/應用程式引擎應用程式

Go 應用程式引擎 SDK 基於 Go 的標準 net/http 套件來提供網路線上請求服務,因此許多 Go 網路伺服器只要修改幾個部分,就能在應用程式引擎中執行。例如,godoc 是以獨立程式的身份包含在 Go 的發行版本中,但它也能以應用程式引擎應用程式的身份執行(godoc 從應用程式引擎中提供 golang.org 服務)。

不過,如果您可以撰寫一個既是獨立網路伺服器又是應用程式引擎應用程式的程式會有多棒?使用 建置限制條件,您就能做到。

建置限制條件是用來決定檔案是否應包含在套件中的行註解。它們最常在能處理各種作業系統或處理器架構的程式碼中使用。例如,path/filepath 套件包含檔案 symlink.go,它會指定建置限制條件,以確保不會在 Windows 系統(不具備符號連結)中建置。

// +build !windows

應用程式引擎 SDK 會導入新的建置限制條件:「appengine」。指定

// +build appengine

的檔案會由應用程式引擎 SDK 建置,並由 go 工具忽略。相反地,指定

// +build !appengine

的檔案會遭到應用程式引擎 SDK 忽略,而 go 工具會正常地建置這些檔案。

goprotobuf 函式庫使用此機制提供其編碼/解碼機制中主要部分的兩個實作:pointer_unsafe.go 是較快速的版本,但無法使用於 App Engine,因為它使用了 unsafe 套件,而 pointer_reflect.go 是較慢的版本,會避免使用 unsafe,而是使用 reflect 套件

讓我們採用一個簡單的 Go 網路伺服器並將它轉換成混合應用程式。這份程式碼是 main.go

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe("localhost:8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello!")
}

使用 go 工具建置它,即可取得獨立的網路伺服器可執行檔。

App Engine 基礎架構會提供自己的 main 函式,會執行等同於 ListenAndServe 的功能。如要將 main.go 轉換成 App Engine 應用程式,請略過呼叫 ListenAndServe 並在初始化函式中註冊處理常式(在 main 之前執行)。以下是 app.go

package main

import (
    "fmt"
    "net/http"
)

func init() {
    http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello!")
}

如要製作混合應用程式,我們需要將它切分成 App Engine 專用的部分、獨立二進位專用的部分,以及共通於兩個版本的部份。在此案例中,沒有 App Engine 專用的部分,因此我們僅將它切分成兩個檔案

app.go 指定並註冊處理常式。它與上述程式碼清單相同,而且不需要建置限制,因為它應該包含於程式碼的所有版本中。

main.go 會執行網路伺服器。它包含 “!appengine” 建置限制,因為它僅必須在建置獨立二進位時包含。

// +build !appengine

package main

import "net/http"

func main() {
    http.ListenAndServe("localhost:8080", nil)
}

如要觀看更複雜的混合應用程式,請參閱 present 工具

結論

我們希望這些變更能讓您更輕鬆地使用具有外部依賴項目的應用程式,以及維護同時包含獨立程式與 App Engine 應用程式的程式。程式庫。

下一篇文章:Concurrency is not parallelism
上一篇文章:Two recent Go talks
Blog Index