Web
- Go內建網路伺服器的package,所以可用於設計web程式,成為主機或進行網路資料傳輸。
Get & Post
- Go提供一個package名為"net/http"來協助搭建Web服務
- : 使用Go http中的Get來取得某網頁資料。
- 使用http.Get將request送給Yahoo網站並取得其回應(resp),使用ioutil.ReadAll()函數讀取response的Body資料。
- : Go http中的Post可以傳送更多資訊。
- 使用http.PostForm()較為簡潔,使用http.Post()需要import "strings"。
Go Web
- 可使用Go建立一個web server。
- : 下例說明如何建立一個基本的web server,需import "net/http"。
- 記得import "net/http這個package。
- 使用http.HandleFunc()來註冊請求"/"的router規則,然後轉到HandleFunc這個函數(serveHTTP)。
- 然後使用http.ListenAndServe(addr string, handler Handler)函數來傾聽在TCP網路上的位址並使用handler呼叫伺服器來處理requests。
- handler通常為nil(使用預設之router -> DefaultServeMux),而ListenAndServe通常傳回non-nil error。
- : 多增加一個網頁。
- 到http://localhost:3000/PageOned可看到另一頁的內容。
- : 再增加一頁並顯示該頁的瀏覽次數。
- sync.Mutex{}用來確保只有一個goroutine可以取用變數,先使用mutex.Lock()鎖定,再使用mutex.Unlock()解鎖。
- : 將首頁改為顯示檔案目錄連結,使用http.ServeFile(w, r, r.URL.Path[1:])。
- http.ServeFile(w, r, r.URL.Path[1:])若將1改為0則顯示根目錄。
- 顯示中若有html file可直接顯示html內容。
- 僅http.ServeFile(w, r, r.URL.Path[1:])與fmt.Fprint()並用則顯示連結文字。
- : 如果只想開放某一資料夾中的檔案,在project directory src/go1/內建一個資料夾名為static(\src\go1\static),並在其中放置檔案。
- 在http://localhost:3000/static/可看到static資料夾中的檔案。
- http.StripPrefix("/static/", fs):in order to strip away part of the URL path to correctly serve files from system。
- : 使用template。
- template.Must()也可以置於tpl.ExecuteTemplate(w, "static1.html", nil)之前(若此去除init())。
- template.Must()也可改為tpl, _ := template.ParseFiles("static/static1.html"),應為tpl, err := template.ParseFiles("static/static1.html")之後再接if err!=nil{...},因不處理err,使用_代替。記得此時需去除tpl的宣告。
- 此時http://localhost:3000/可看到static1.html的內容。
template
- 使用MVC(Model, View, Controller)設計模式,Models解析data,views顯示結果,controllers處理使用者的requests。在views的部分,常使用static HTML files當作模組,僅改變部分要顯示的資料,此稱為template,template可以方便重複使用。
- : 先建立一個簡單的template,需要import "html/template"。
- 建立一個type名為User,其中僅有一個變數UserName。
- New()一個template,使用Parse()函數解析型態,然後使用Execute()將物件(user)與模組(t)合併。
- : 如果項目中包含陣列,使用range關鍵字來取得所有資料,最後加上{{end}}。
- 使用``代替"",字串可以換行。
- : 如果type中包含其他type的array,e.g.。
- 使用with .Accounts表示對於參數accounts[],因為accounts是陣列,所以再使用range .。
- 如果accounts不是array,那首先去除template中的{{range .}}與{{end}},然後使用Accounts: &a1即可,若不傳址,也可傳值。
- : 使用if...else...判斷。
- if之後的condition是boolean值,不能做運算(e.g. !.Closed)。
- : 接下來試著使用設計template並將其用於網頁顯示,首先設計一個最簡單的template名為layout.html,並將程式碼修改如下:。
- layout.html置於以下檔案路徑workspace\src\go1\static,go1.go的檔案目錄則為workspace\src\go1(go1為project name)。
- 可以使用tpl.Execute()或tpl.ExecuteTemplate()來執行(輸入參數不同)。
- 使用map來對應layout.html中的PageTitle與其值。
- : template內對應的參數可能會越來越多,所以使用map會較不好管理,因此設計成struct會比較清楚。
- : 增加一些元件,並使用unordered list將其表列。
- 另外設計一個type Item並在type Page中增加一個Item的array。
- 在layout.html中使用range...end來對每一個item進行表列。
- : 接下來增加if...else到template。
- 如前所述,if僅接受boolean值,不能做運算。
- : 如果有兩個template要如何應用。
- 在Go的設計中,為了區別也可以將template的延伸檔名訂為gohtml,在此例中使用gohtml(但此檔案在有些編輯器無法對關鍵字顯示顏色)。
- 在layout.gohtml中使用{{define "layout"}}...{{end}}來含括一個tempalte,{{end}}表示template的結尾。因此可以再設計另一個template在{{define "bodyLayout"}}...{{end}}。
- 請注意在template layout中包含另一個template bodyLayout,此稱為Nested template。因為bodyLayout要取得目前的資料,所以在納入時要寫{{template "bodyLayout" .}},其中的.表示目前資料。
- 顯然可以將不同的template寫在不同的檔案內。
- 在layout.html內包含了bodyLayout與footerLayout兩個tempalte,所以設計三個檔案並以layout.html為主體。
- 因為超過一個template檔案,所以必須在template.ParseFiles()函數內將所有使用到的template檔案都納入。
- 再增加一點複雜度,如果Author是一個物件(type),所以需要設計一個AuthorInfo的type,且在footerLayout處的Author需做修改如下 。
- type AuthorInfo將fistname與lastname分為兩個參數,所以在footerLayout.html內使用{{.FirstName}} {{.LastName}}。
- 在嵌入{{template "footerLayout" .Author}}時使用.Author表示使用目前資料內的Author的資料。
- 也可以使用{{template "footerLayout" .}},footerLayout.html內則需使用{{.Author.FirstName}} {{.Author.LastName}}。
- 綜合以上,可以設計一個基本的版面模組,其中且分為header,body,footer等不同部分,分別根據每一部分設計多個不同的template,屆時只需要隨需要組合即可。
layout.html
go1.go
layout.html
go1.go
layout.html
go1.go
layout.gohtml
go1.go
layout.html
bodyLayout.html
footerLayout.html
go1.go
footerLayout.html
layout.html
go1.go