使用golang可以很容易的创建restful格式的web程序。对于比较简单的应用,使用”net/http”模块多写几个函数就可以实现路由了,不过对于稍复杂一点的应用,该模块就显的不友好,这时候可以使用gorilla/mux或httproute模块实现路由,gin web框架使用的httproute,不过一般mux使用的比较多。本篇就结合mux模块实现一个简单的小示例。
一、基于net/http的示例
其代码如下:
package main import ( "fmt" "log" "net/http" ) func homePage(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "Welcome to the HomePage!") fmt.Println("Endpoint Hit: homePage") } func handleRequests() { http.HandleFunc("/", homePage) log.Fatal(http.ListenAndServe(":8081", nil)) } func main() { handleRequests() }
二、json和RESTful改造
一个标准的RESTful API一般需要支持 CREATE, READ, UPDATE 、DELETE操作。一般使用的常见格式为JSON格式。现按如下方式操作下。先定义一个json的结构体:
type Article struct { Title string `json:"Title"` Desc string `json:"desc"` Content string `json:"content"` } type Articles []Article
再创建一个返回所有内容的函数方法:
func returnAllArticles(w http.ResponseWriter, r *http.Request){ articles := Articles{ Article{Title: "Hello", Desc: "Article Description", Content: "Article Content"}, Article{Title: "Hello 2", Desc: "Article Description", Content: "Article Content"}, } fmt.Println("Endpoint Hit: returnAllArticles") json.NewEncoder(w).Encode(articles) }
在不用gorilla/mux模块的情况下,我们使用如下代码:
func handleRequests() { http.HandleFunc("/", homePage) http.HandleFunc("/all", returnAllArticles) log.Fatal(http.ListenAndServe(":8081", nil)) }
运行后访问 URL http://localhost:8081/all,返回的结果如下:
[ { Title: "Hello", desc: "Article Description", content: "Article Content" }, { Title: "Hello 2", desc: "Article Description", content: "Article Content" } ];
三、改用Routers
改用gorilla/mux模块,修改下main函数,内容如下:
package main import ( "fmt" "log" "net/http" "encoding/json" "github.com/gorilla/mux" ) … // Existing code from above func handleRequests() { myRouter := mux.NewRouter().StrictSlash(true) myRouter.HandleFunc("/", homePage) myRouter.HandleFunc("/all", returnAllArticles) log.Fatal(http.ListenAndServe(":10000", myRouter)) } func main() { fmt.Println("Rest API v2.0 - Mux Routers") handleRequests() }
增加路径变量:
myRouter.HandleFunc("/article/{id}", returnSingleArticle)
修改结构体,增加ID参数,如下:
type Article struct { Id int `json:"Id"` Title string `json:"Title"` Desc string `json:"desc"` Content string `json:"content"` }
增加ID查询函数:
func returnSingleArticle(w http.ResponseWriter, r *http.Request){ vars := mux.Vars(r) key := vars["id"] fmt.Fprintf(w, "Key: " + key) }
比如访问http://localhost:1000/article/1 ,其就会返回key:1 。当然我们也可以修改为增加多个变量,比如发下:
func returnSingleArticle(w http.ResponseWriter, r *http.Request){ vars := mux.Vars(r) key := vars["key"] var1 := vars["var1"] var2 := vars["var2"] fmt.Println("Var 1: " + var1) fmt.Println("Var 2: " + var2) fmt.Fprintf(w, "Key: " + key) } func handleRequests() { myRouter := mux.NewRouter().StrictSlash(true) myRouter.HandleFunc("/", homePage) myRouter.HandleFunc("/all", returnAllArticles) myRouter.HandleFunc("/article/{key}/{var1}/{var2}/", returnSingleArticle) log.Fatal(http.ListenAndServe(":10000", myRouter)) }
这里就有三个变量。其访问格式为:http://localhost:10000/article/1/1/2/ 。
四、完整代码
完整代码如下:
package main import ( "encoding/json" "fmt" "log" "net/http" "github.com/gorilla/mux" ) // Article - Our struct for all articles type Article struct { Id int `json:"Id"` Title string `json:"Title"` Desc string `json:"desc"` Content string `json:"content"` } type Articles []Article func homePage(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Welcome to the HomePage!") fmt.Println("Endpoint Hit: homePage") } func returnAllArticles(w http.ResponseWriter, r *http.Request) { articles := Articles{ Article{Title: "Hello", Desc: "Article Description", Content: "Article Content"}, Article{Title: "Hello 2", Desc: "Article Description", Content: "Article Content"}, } fmt.Println("Endpoint Hit: returnAllArticles") json.NewEncoder(w).Encode(articles) } func returnSingleArticle(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) key := vars["id"] fmt.Fprintf(w, "Key: "+key) } func handleRequests() { myRouter := mux.NewRouter().StrictSlash(true) myRouter.HandleFunc("/", homePage) myRouter.HandleFunc("/all", returnAllArticles) myRouter.HandleFunc("/article/{id}", returnSingleArticle) log.Fatal(http.ListenAndServe(":10000", myRouter)) } func main() { handleRequests() }