使用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()
}