如何在 Google Cloud 撰寫和部署 Go 程式

Google 雲端 App Engine, 除了可以用 Python, Java, PHP 語言來撰寫程式以外, 也可以用 Go 語言, 這裡教大家怎麼開始. 但我們不用 App Engine 來部署, 改用 Container Engine (still in Beta).

  1. 當然要先申請一個 Google Cloud 帳號 (免費試用, 價值NT$9,300 使用 60 天) -> https://cloud.google.com/free-trial/
  2. 建議大家盡量用 Google Container Engine (docker), 而非 App Engine, 因為 container 終究會比較便宜, 而且也比較有彈性. 因此, 這裡選擇用 flexible 環境 (做 beta 測試, 也不用錢) -> https://cloud.google.com/appengine/docs/flexible/go/quickstart
  3. [假設一] 你已經安裝好 go 開發環境, 如果還沒有, 請點選 -> (install go), 或直接進入你 Google Cloud Console 的 Google Cloud Shell (>_ ), 那裡也有一個免費電腦, 安裝好 go 語言.

4. 用 Google Cloud Shell 為例, (你也可以在 local 電腦, 先測試你的 go 程式) 如下圖, 如果您執行 goapp serve 後, 選擇左上角的 Web preview icon 就能顯示你 http://0.0.0.0:8080 網頁內容.

5. 執行測試程式 guestbook 如下

git clone https://github.com/GoogleCloudPlatform/appengine-guestbook-go.git
cd appengine-guestbook-go/
git fetch
git checkout part4-usingdatastore
goapp serve

顯示網頁結果如下:

6. 部署到正式網址, https://oidc-1339.appspot.com/ , 這裡 oidc-1339 是你當下 Google cloud 的 Project ID, 以下範例以 mingderwang 帳號為例, 如果你 username 為 alex, GOPATH 就換成 /home/alex/gopath (在 Google Cloud Shell 下為例)

export GOPATH=/home/mingderwang/gopath
go get -u -d github.com/GoogleCloudPlatform/golang-samples/appengine_flexible/helloworld
cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/appengine_flexible/helloworld
aedeploy gcloud app deploy

7. 我們利用 GOogle 所提供的範例程式, 來測試部署, 有兩個檔案 app.yml 與 helloworld.go 內容如下; 從 app.yml env: flex 看出來, 它是部署在 flexible 環境 (舊名稱叫 Managed VMs), 而非 App Engine 環境!

$ cat app.yml

runtime: go
env: flex

$ cat helloworld.go

// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// Sample helloworld is a basic App Engine flexible app.
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handle)
http.HandleFunc("/_ah/health", healthCheckHandler)
log.Print("Listening on port 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handle(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
fmt.Fprint(w, "Hello world!")
}
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "ok")
}