Go 通關:RESTful API 服務,急速入門!

RESTful API

EST 即表述性狀態傳遞(英文:Representational State Transfer,簡稱 REST),它是一種針對網絡應用的設計和開發方式,可以降低開發的複雜性,提高系統的可伸縮性。(引用自百度百科)。

HTTP Method

  1. 早在 HTTP 0.9 版本中,只有一個 GET 方法,該方法是一個冪等方法,用於獲取服務器上的資源;

  2. HTTP 1.0 版本中又增加了 HEAD 和 POST 方法,其中常用的是 POST 方法,一般用於給服務端提交一個資源。

  3. HTTP1.1 版本的時,又增加了幾個方法。總共加起來有 9 個。
    它們的作用:

在 RESTful API 中,使用的主要是以下五種 HTTP 方法:

一個簡單的 RESTful API

Golang 提供了內置的 net/http 包,用來處理這些 HTTP 請求,可以比較方便地開發一個 HTTP 服務。

示例:

package main

import (
 "fmt"
 "net/http"
)

func main() {
 http.HandleFunc("/users",handleUsers)
 http.ListenAndServe(":8080", nil)
}
func handleUsers(w http.ResponseWriter, r *http.Request){
 fmt.Fprintln(w,"ID:1,Name:張三")
 fmt.Fprintln(w,"ID:2,Name:李四")
 fmt.Fprintln(w,"ID:3,Name:王五")
}

運行程序後,在瀏覽器中輸入 http://localhost:8080/users, 就可以看到如下內容信息:

ID:1,Name:張三
ID:2,Name:李四
ID:3,Name:王五

示例中,不光可以用 GET 能進行訪問,POST、PUT 等也可以,接下來對示例進行改進,使它使它符合 RESTful API 的規範:

package main

import (
 "fmt"
 "net/http"
)

func main() {
 http.HandleFunc("/users",handleUsers)
 http.ListenAndServe(":8080", nil)
}
func handleUsers(w http.ResponseWriter, r *http.Request){
 switch r.Method {
 case "GET":
  w.WriteHeader(http.StatusOK)
  fmt.Fprintln(w,"ID:1,Name:張三")
  fmt.Fprintln(w,"ID:2,Name:李四")
  fmt.Fprintln(w,"ID:3,Name:王五")
 default:
  w.WriteHeader(http.StatusNotFound)
  fmt.Fprintln(w,"not found")
 }
}

我們在 handleUsers 函數中增加了只在使用 GET 方法時,才獲得所有用戶的信息,其他情況返回 not found。

RESTful JSON API

在項目接口中,數據大多數情況下會使用 json 格式來傳輸,再次對示例進行改造,使它返回 json 格式的內容:

package main

import (
 "encoding/json"
 "fmt"
 "net/http"
)

func main() {
 http.HandleFunc("/users",handleUsers)
 http.ListenAndServe(":8080", nil)
}
//數據源,模擬MySQL中的數據
var users = []User{
 {ID: 1,Name: "張三"},
 {ID: 2,Name: "李四"},
 {ID: 3,Name: "王五"},
}
func handleUsers(w http.ResponseWriter, r *http.Request){
 switch r.Method {
 case "GET":
  users,err:=json.Marshal(users)
  if err!=nil {
   w.WriteHeader(http.StatusInternalServerError)
   fmt.Fprint(w,"{\"message\": \""+err.Error()+"\"}")
  }else {
   w.WriteHeader(http.StatusOK)
   w.Write(users)
  }
 default:
  w.WriteHeader(http.StatusNotFound)
  fmt.Fprint(w,"{\"message\": \"not found\"}")
 }
}
//用戶
type User struct {
 ID int
 Name string
}

運行結果:

[{"ID":1,"Name":"張三"},{"ID":2,"Name":"李四"},{"ID":3,"Name":"王五"}]

這次,我們新建了一個 User 結構體,使用 users 這個切片存儲所有的用戶,然後在 handleUsers 函數中把它轉化爲一個 JSON 數組返回。

Gin 框架

上面我們使用的是 Go 語言自帶的  net/http 包,寫法比較簡單,但是它也有許多不足之處:

基於以上的不足,我們可以使用其它的 Golang Web 框架,例如今天要介紹的 Gin 框架。

引入 Gin 框架

Gin 框架是一個在 Github 上開源的 Web 框架,它封裝了很多 Web 開發需要的功能,而且性能也非常高,可以很容易地寫出 RESTful API。
Gin 框架其實是一個模塊,採用 Go Mod 的方法引入即可:

  1. 下載安裝 Gin 框架go get -u github.com/gin-gonic/gin

  2. 在 Go 語言代碼中導入使用import "github.com/gin-gonic/gin"

使用 Gin 框架

我們使用 Gin 框架來重寫上面的示例:

package main

import "github.com/gin-gonic/gin"

func main() {
 r := gin.Default()
 r.GET("/users", listUser)
 r.Run(":8080")
}
func listUser(c *gin.Context) {
 c.JSON(200, users)
}

//數據源,模擬MySQL中的數據
var users = []User{
 {ID: 1, Name: "張三"},
 {ID: 2, Name: "李四"},
 {ID: 3, Name: "王五"},
}

//用戶
type User struct {
 ID   int
 Name string
}

對比 net/http 包,Gin 框架的代碼非常簡單,通過 GET 方法就可以創建一個只處理 HTTP GET 方法的服務,且使用 c.JSON 方法便可輸出 JSON 格式的數據。
通過 Run 方法啓動 HTTP 服務,監聽 8080 端口。運行這個 Gin 示例,在瀏覽器中輸入 http://localhost:8080/users,可以看到和通過 net/http 包實現的效果是一樣的。

獲取一個用戶

獲取一個用戶的信息,我們使用 GET 方法,設計的 URL 格式爲 :
http://localhost:8080/users/1
url 中的數字 1 爲用戶 id,我們通過 id 來獲取一個指定的用戶:

func main() {
   //省略其它沒有改動過的代碼
   r.GET("/users/:id", getUser)
}
func getUser(c *gin.Context) {
   id := c.Param("id")
   var user User
   found := false
   //類似於數據庫的SQL查詢
   for _, u := range users {
      if strings.EqualFold(id, strconv.Itoa(u.ID)) {
         user = u
         found = true
         break
      }
   }
   if found {
      c.JSON(200, user)
   } else {
      c.JSON(404, gin.H{
         "message""用戶不存在",
      })
   }
}

在 Gin 框架中,路徑中使用冒號表示 Path 路徑參數,比如示例中的 :id,然後通過 c.Param("id") 獲取需要查詢用戶的 ID 值。
運行示例,訪問地址 http://localhost:8080/users/1 ,便可以獲取 ID 爲 1 的用戶:{"ID":1,"Name":"張三"}

新增一個用戶

新增一個用戶的 URL 格式爲:
http://localhost:8080/users
向這個 URL 發送數據,就可以新增一個用戶.

func main() {
   //省略其它沒有改動過的代碼
   r.POST("/users", createUser)
}
func createUser(c *gin.Context) {
   name := c.DefaultPostForm("name""")
   if name != "" {
      u := User{ID: len(users) + 1, Name: name}
      users = append(users, u)
      c.JSON(http.StatusCreated,u)
   } else {
      c.JSON(http.StatusOK, gin.H{
         "message""請輸入用戶名稱",
      })
   }
}

新增用戶的邏輯是獲取客戶端上傳的 name 值,然後生成一個 User 用戶,最後把它存儲到 users 集合中。
我們使用 curl 命令發送一個新增用戶請求:

curl -X POST -d 'name=無塵' http://localhost:8080/users
{"ID":4,"Name":"無塵"}

可以看到,新增用戶成功,且返回了新增的用戶及分配的 ID。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/bWlczebW1Ihcw5P0FlWFTA