1. 程式人生 > >Go實戰--實現簡單的restful api(The way to go)

Go實戰--實現簡單的restful api(The way to go)

生命不止,繼續 go go go !!!

今天跟大家介紹一下如何使用go建立一套restful api,我們依託於開源庫gorilla/mux。

let’s go~~

何為RESTful API

A RESTful API is an application program interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data.

A RESTful API – also referred to as a RESTful web service – is based on representational state transfer (REST) technology, an architectural style and approach to communications often used in web services development.

Wikipedia: 表徵性狀態傳輸(英文:Representational State Transfer,簡稱REST)是Roy Fielding博士於2000年在他的博士論文中提出來的一種軟體架構風格。
Roy Fielding是HTTP協議(1.0版和1.1版)的主要設計者,事實上HTTP 1.1規範正是基於REST架構風格的指導原理來設計的。需要注意的是,REST是一種設計風格而不是標準,如果一個架構符合REST原則,我們就稱它為RESTful架構。

這裡寫圖片描述

gorilla/mux

golang自帶的http.SeverMux路由實現簡單,本質是一個map[string]Handler,是請求路徑與該路徑對應的處理函式的對映關係。實現簡單功能也比較單一:

  1. 不支援正則路由, 這個是比較致命的
  2. 只支援路徑匹配,不支援按照Method,header,host等資訊匹配,所以也就沒法實現RESTful架構

而gorilla/mux是一個強大的路由,小巧但是穩定高效,不僅可以支援正則路由還可以按照Method,header,host等資訊匹配,可以從我們設定的路由表示式中提取出引數方便上層應用,而且完全相容http.ServerMux

設定好了go的環境變數,直接執行:

go get -u github.com/gorilla/mux

實現

定義結構體,使用者構造json

type Person struct {
    ID        string
`json:"id,omitemty"` Firstname string `json:"firstname,omitempty"` Lastname string `json:"lastname,omitempty"` Address *Address `json:"address,omitempty"` } type Address struct { City string `json:"city,omitempty"` Province string `json:"province,omitempty"` }

接下來,定義一個全域性變數,用於儲存資源(資料):

var people []Person

對這個變數進行賦值:

    people = append(people, Person{ID: "1", Firstname: "xi", Lastname: "dada", Address: &Address{City: "Shenyang", Province: "Liaoning"}})
    people = append(people, Person{ID: "2", Firstname: "li", Lastname: "xiansheng", Address: &Address{City: "Changchun", Province: "Jinlin"}})

Get
獲取所有person,這裡我們叫people:

func GetPeople(w http.ResponseWriter, req *http.Request) {
    json.NewEncoder(w).Encode(people)
}

根據id獲取person:

func GetPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for _, item := range people {
        if item.ID == params["id"] {
            json.NewEncoder(w).Encode(item)
            return
        }
    }
    json.NewEncoder(w).Encode(people)
}

然後handle function:

    router := mux.NewRouter()
    router.HandleFunc("/people", GetPeople).Methods("GET")
    router.HandleFunc("/people/{id}", GetPerson).Methods("GET")

post
同樣可以,通過post操作向伺服器新增資料:

func PostPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    var person Person
    _ = json.NewDecoder(req.Body).Decode(&person)
    person.ID = params["id"]
    people = append(people, person)
    json.NewEncoder(w).Encode(people)
}

然後handle function:

router.HandleFunc("/people/{id}", PostPerson).Methods("POST")

Delete
根據id進行刪除操作:

func DeletePerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for index, item := range people {
        if item.ID == params["id"] {
            people = append(people[:index], people[index+1:]...)
            break
        }
    }
    json.NewEncoder(w).Encode(people)
}

然後handle function:

router.HandleFunc("/people/{id}", DeletePerson).Methods("DELETE")

完整程式碼與執行結果

程式碼:

package main

import (
    "encoding/json"
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

type Person struct {
    ID        string   `json:"id,omitemty"`
    Firstname string   `json:"firstname,omitempty"`
    Lastname  string   `json:"lastname,omitempty"`
    Address   *Address `json:"address,omitempty"`
}

type Address struct {
    City     string `json:"city,omitempty"`
    Province string `json:"province,omitempty"`
}

var people []Person

func GetPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for _, item := range people {
        if item.ID == params["id"] {
            json.NewEncoder(w).Encode(item)
            return
        }
    }
    json.NewEncoder(w).Encode(people)
}

func GetPeople(w http.ResponseWriter, req *http.Request) {
    json.NewEncoder(w).Encode(people)
}

func PostPerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    var person Person
    _ = json.NewDecoder(req.Body).Decode(&person)
    person.ID = params["id"]
    people = append(people, person)
    json.NewEncoder(w).Encode(people)
}

func DeletePerson(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for index, item := range people {
        if item.ID == params["id"] {
            people = append(people[:index], people[index+1:]...)
            break
        }
    }
    json.NewEncoder(w).Encode(people)
}

func main() {
    router := mux.NewRouter()
    people = append(people, Person{ID: "1", Firstname: "xi", Lastname: "dada", Address: &Address{City: "Shenyang", Province: "Liaoning"}})
    people = append(people, Person{ID: "2", Firstname: "li", Lastname: "xiansheng", Address: &Address{City: "Changchun", Province: "Jinlin"}})
    router.HandleFunc("/people", GetPeople).Methods("GET")
    router.HandleFunc("/people/{id}", GetPerson).Methods("GET")
    router.HandleFunc("/people/{id}", PostPerson).Methods("POST")
    router.HandleFunc("/people/{id}", DeletePerson).Methods("DELETE")
    log.Fatal(http.ListenAndServe(":12345", router))
}

執行結果:
Get People
這裡寫圖片描述

package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {

    url := "http://localhost:12345/people"

    req, _ := http.NewRequest("GET", url, nil)

    req.Header.Add("accept", "application/json")
    req.Header.Add("authorization", "Basic d2FuZ3NodWJvOndhbmdzaHVibw==")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "18774413-0c11-e312-7ed6-7bc4f8151f5a")

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}

Get Person
這裡寫圖片描述

package main

import (
    "fmt"
    "strings"
    "net/http"
    "io/ioutil"
)

func main() {

    url := "http://localhost:12345/people/1"

    payload := strings.NewReader("{\n  \"firstname\": \"wang\",\n  \"lastname\": \"shubo\",\n  \"address\": {\n    \"city\": \"Beijing\",\n    \"state\": \"Beijng\"\n  }\n}")

    req, _ := http.NewRequest("DELETE", url, payload)

    req.Header.Add("content-type", "application/json")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "4a894ad6-2887-259a-c953-5d26fed70963")

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}

Post Person
這裡寫圖片描述

package main

import (
    "fmt"
    "strings"
    "net/http"
    "io/ioutil"
)

func main() {

    url := "http://localhost:12345/people/3"

    payload := strings.NewReader("{\n  \"firstname\": \"wang\",\n  \"lastname\": \"shubo\",\n  \"address\": {\n    \"city\": \"Beijing\",\n    \"state\": \"Beijng\"\n  }\n}")

    req, _ := http.NewRequest("POST", url, payload)

    req.Header.Add("content-type", "application/json")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "a9d590dd-1819-15f6-962e-0eabf4b7e707")

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}

Delete Person
這裡寫圖片描述

package main

import (
    "fmt"
    "strings"
    "net/http"
    "io/ioutil"
)

func main() {

    url := "http://localhost:12345/people/1"

    payload := strings.NewReader("{\n  \"firstname\": \"wang\",\n  \"lastname\": \"shubo\",\n  \"address\": {\n    \"city\": \"Beijing\",\n    \"state\": \"Beijng\"\n  }\n}")

    req, _ := http.NewRequest("DELETE", url, payload)

    req.Header.Add("content-type", "application/json")
    req.Header.Add("cache-control", "no-cache")
    req.Header.Add("postman-token", "4c8d290e-4c6c-53f7-64e9-1d1f6ed19b09")

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}