使用golang可以很容易的创建restful格式的web程序。对于比较简单的应用,使用”net/http”模块多写几个函数就可以实现路由了,不过对于稍复杂一点的应用,该模块就显的不友好,这时候可以使用gorilla/mux或httproute模块实现路由,gin web框架使用的httproute,不过一般mux使用的比较多。本篇就结合mux模块实现一个简单的小示例。

一、基于net/http的示例

其代码如下:

 1package main
 2import (
 3    "fmt"
 4    "log"
 5    "net/http"
 6)
 7func homePage(w http.ResponseWriter, r *http.Request){
 8    fmt.Fprintf(w, "Welcome to the HomePage!")
 9    fmt.Println("Endpoint Hit: homePage")
10}
11func handleRequests() {
12    http.HandleFunc("/", homePage)
13    log.Fatal(http.ListenAndServe(":8081", nil))
14}
15func main() {
16    handleRequests()
17}

二、json和RESTful改造

一个标准的RESTful API一般需要支持 CREATE, READ, UPDATE 、DELETE操作。一般使用的常见格式为JSON格式。现按如下方式操作下。先定义一个json的结构体:

1type Article struct {
2    Title string `json:"Title"`
3    Desc string `json:"desc"`
4    Content string `json:"content"`
5}
6type Articles []Article

再创建一个返回所有内容的函数方法:

1func returnAllArticles(w http.ResponseWriter, r *http.Request){
2    articles := Articles{
3        Article{Title: "Hello", Desc: "Article Description", Content: "Article Content"},
4        Article{Title: "Hello 2", Desc: "Article Description", Content: "Article Content"},
5    }
6    fmt.Println("Endpoint Hit: returnAllArticles")
7    json.NewEncoder(w).Encode(articles)
8}

在不用gorilla/mux模块的情况下,我们使用如下代码:

1func handleRequests() {
2    http.HandleFunc("/", homePage)
3    http.HandleFunc("/all", returnAllArticles)
4    log.Fatal(http.ListenAndServe(":8081", nil))
5}

运行后访问 URL http://localhost:8081/all, 返回的结果如下:

 1[
 2  {
 3    Title: "Hello",
 4    desc: "Article Description",
 5    content: "Article Content"
 6  },
 7  {
 8    Title: "Hello 2",
 9    desc: "Article Description",
10    content: "Article Content"
11  }
12];

三、改用Routers

改用gorilla/mux模块,修改下main函数,内容如下:

 1package main
 2import (
 3    "fmt"
 4    "log"
 5    "net/http"
 6    "encoding/json"
 7    "github.com/gorilla/mux"
 8)
 9 // Existing code from above
10func handleRequests() {
11    myRouter := mux.NewRouter().StrictSlash(true)
12    myRouter.HandleFunc("/", homePage)
13    myRouter.HandleFunc("/all", returnAllArticles)
14    log.Fatal(http.ListenAndServe(":10000", myRouter))
15}
16func main() {
17    fmt.Println("Rest API v2.0 - Mux Routers")
18    handleRequests()
19}

增加路径变量:

1myRouter.HandleFunc("/article/{id}", returnSingleArticle)

修改结构体,增加ID参数,如下:

1type Article struct {
2    Id             int         `json:"Id"`
3    Title   string `json:"Title"`
4    Desc    string `json:"desc"`
5    Content string `json:"content"`
6}

增加ID查询函数:

1func returnSingleArticle(w http.ResponseWriter, r *http.Request){
2    vars := mux.Vars(r)
3    key := vars["id"]
4    fmt.Fprintf(w, "Key: " + key)
5}

比如访问http://localhost:1000/article/1 ,其就会返回key:1 。当然我们也可以修改为增加多个变量,比如发下:

 1func returnSingleArticle(w http.ResponseWriter, r *http.Request){
 2    vars := mux.Vars(r)
 3    key := vars["key"]
 4    var1 := vars["var1"]
 5    var2 := vars["var2"]
 6    fmt.Println("Var 1: " + var1)
 7    fmt.Println("Var 2: " + var2)
 8    fmt.Fprintf(w, "Key: " + key)
 9}
10func handleRequests() {
11    myRouter := mux.NewRouter().StrictSlash(true)
12    myRouter.HandleFunc("/", homePage)
13    myRouter.HandleFunc("/all", returnAllArticles)
14    myRouter.HandleFunc("/article/{key}/{var1}/{var2}/", returnSingleArticle)
15    log.Fatal(http.ListenAndServe(":10000", myRouter))
16}

这里就有三个变量。其访问格式为:http://localhost:10000/article/1/1/2/ 。

四、完整代码

完整代码如下:

 1package main
 2import (
 3    "encoding/json"
 4    "fmt"
 5    "log"
 6    "net/http"
 7    "github.com/gorilla/mux"
 8)
 9// Article - Our struct for all articles
10type Article struct {
11    Id      int    `json:"Id"`
12    Title   string `json:"Title"`
13    Desc    string `json:"desc"`
14    Content string `json:"content"`
15}
16type Articles []Article
17func homePage(w http.ResponseWriter, r *http.Request) {
18    fmt.Fprintf(w, "Welcome to the HomePage!")
19    fmt.Println("Endpoint Hit: homePage")
20}
21func returnAllArticles(w http.ResponseWriter, r *http.Request) {
22    articles := Articles{
23        Article{Title: "Hello", Desc: "Article Description", Content: "Article Content"},
24        Article{Title: "Hello 2", Desc: "Article Description", Content: "Article Content"},
25    }
26    fmt.Println("Endpoint Hit: returnAllArticles")
27    json.NewEncoder(w).Encode(articles)
28}
29func returnSingleArticle(w http.ResponseWriter, r *http.Request) {
30    vars := mux.Vars(r)
31    key := vars["id"]
32    fmt.Fprintf(w, "Key: "+key)
33}
34func handleRequests() {
35    myRouter := mux.NewRouter().StrictSlash(true)
36    myRouter.HandleFunc("/", homePage)
37    myRouter.HandleFunc("/all", returnAllArticles)
38    myRouter.HandleFunc("/article/{id}", returnSingleArticle)
39    log.Fatal(http.ListenAndServe(":10000", myRouter))
40}
41func main() {
42    handleRequests()
43}