Go語言構(gòu)建 RESTful Web 服務(wù)
本文是 Hardcore Google 系列的一部分,本系列的其它部分于下面地址可以找到:
Go 語言實現(xiàn) REST 風格網(wǎng)絡(luò)服務(wù)器
在開始著手開發(fā)網(wǎng)絡(luò)應(yīng)用之前,你需要先選擇你所用的工具集,以及它們之間的相互作用,這一步很重要。在我的項目中,我選擇 Go 語言作為后臺,AngularJS 作為前臺,而 Google App Engine 則為主機。于是,剩下的問題就是,Go 語言如何同 AngularJS 交互。幸運的是,這真的太簡單了。
我選擇以 REST風格的 API 進行交互,因為這樣交互的方法組織良好,且網(wǎng)絡(luò)應(yīng)用的前端后端對其都支持良好。在我的開發(fā)生涯中,我發(fā)現(xiàn),我為了將兩種格格不如的東西統(tǒng)合到一起浪費了太多頭腦,頭發(fā)都掉了不少,REST 很好。
使用 REST 風格的網(wǎng)絡(luò)服務(wù)器意味著你將基于 HTTP 方法(例如 GET、POST、DELETE等)和URL網(wǎng)址管理你的數(shù)據(jù)。在 Go 語言的一端,你可以使用 net/http 包來處理 AngularJS 提交的請求。而在更高一級,你可以這樣告訴 Go 語言如何處理請求:
- http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "Thanks for the %s!", r.Method)
- })
上面我們注冊了一個處理所有請求 /bar 的函數(shù)。每個對請求的處理函數(shù)都有相同的函數(shù)定義: 它以參數(shù)的形式,獲得輸出響應(yīng)的 http.ResponseWriter 和包含請求細節(jié)的 http.Request。這樣,當我們啟動這個服務(wù),并發(fā)起一個 “DELETE /bar” 請求時,我們將獲得 “Thanks for the DELETE!” 的返回。
我希望,你可以看看下一步的處理。在 Go 語言中實現(xiàn) REST 風格的 API,你需要為每個 URL 網(wǎng)址節(jié)點注冊處理函數(shù),并根據(jù)給出的方法實現(xiàn)處理程序。通過使用 gorilla/mux 包,這個過程將更簡單。它比 Go 語言默認的 HTTP 處理器更底層,但它能夠更好的通過 HTTP 方法處理路由細節(jié)。下面就是例子:
- m := mux.NewRouter()
- // Get all lists.
- m.HandleFunc("/", GetAllLists).Methods("GET")
- // Make a new list.
- m.HandleFunc("/", PostList).Methods("POST")
- // Singe list operations.
- m.HandleFunc("/{key}/", GetList).Methods("GET")
- m.HandleFunc("/{key}/", PutList).Methods("PUT")
- m.HandleFunc("/{key}/", DeleteList).Methods("DELETE")
- // Everything else fails.
- m.HandleFunc("/{path:.*}", gorca.NotFoundFunc)
如你所見,我為每個需要的 REST 方法都注冊了處理程序。在這個例子里,我為網(wǎng)絡(luò)應(yīng)用的列表部分注冊了一些函數(shù)。我可以通過 GET 或是 POST 在根路徑( /)獲取和提交列表。如果我在 URL 中設(shè)定了一個鍵(/{key}/),我可以處理一個指定的列表。這樣,我可以通過GET, PUT和DELETE。獲取列表,上傳列表,或是刪除列表。
***的 HandleFunc 則用來處理其它未設(shè)定的請求。如果客戶端的請求并未明確列出,我們將返回一個404狀態(tài)和 JSON 格式的細節(jié)信息。net/http 包可以返回了一個簡單的404狀態(tài),但我希望同時能返回 JSON響應(yīng)。 使用全部抓取將允許我返回 JSON響應(yīng)。客戶端則可以為用戶顯示一個有效的信息,提示錯誤所在,而不僅僅是一個簡單的“請求失敗”。
作為處理器(handler)的例子, GetAllLists 處理器代碼如下:
- // GetAllLists fetches all of the lists.
- func GetAllLists(w http.ResponseWriter, r *http.Request) {
- // Create the query.
- c := appengine.NewContext(r)
- q := datastore.NewQuery("List").Order("-LastModified")
- // Fetch the lists.
- lists := []List{}
- if _, err := q.GetAll(c, &lists); err != nil {
- gorca.LogAndUnexpected(c, w, r, err)
- return
- }
- // Write the lists as JSON.
- gorca.WriteJSON(c, w, r, lists)
- }
如果你對 App Engine 不是很熟悉,代碼中的一些細節(jié)或許對你有些模糊,但我基本上獲取了 App Engine datastore 中的所有的列表數(shù)據(jù),并將其轉(zhuǎn)換為 JSON,作為響應(yīng)返回。
GetAllLists 函數(shù)顯示了 Go 如何同 App Engine 相結(jié)合,使開發(fā)變得簡單。短短的十幾行代碼,我可以創(chuàng)造一個強大的 REST 網(wǎng)絡(luò)服務(wù)器。我不必處理 MySQL 的連接、用戶認證、或解析傳入的 HTTP 請求。 App Engine 和 Go 已經(jīng)為我做了處理。最終的結(jié)果就是,我擁有了更具可讀性、可測試性和可維護性的代碼。
你可以在我的代碼中看到我是如何為此而著迷的:
列表處理器函數(shù)(The List Handler Functions)
我真的驚訝于如此簡易的過程。安裝后臺環(huán)境很可能成為一個夢魘。在工作中,我曾處理過一個 SOAP 網(wǎng)絡(luò)服務(wù),我愿出庭作證:這個'S'(簡易的)是一個謊言。而對 Go,這根本不是什么事兒。它已經(jīng)提供了強大的功能,且開源則意味著,只要你需要,大批如同 gorilla/mux 的包有的是。下一次,我將說說如何利用 Angular JS 處理我們發(fā)回的JSON。敬請期待。
原文鏈接:http://www.oschina.net/translate/hardcore-google-communicating-go