banner

Gin开发RESTful应用(一)

分类: Go |发布时间: 10/21/2018, |修改时间: 11/26/2018, |共有 0 条评论 点此返回

本文记录了使用Go的HTTP框架gin-gonic和MySQL数据库开发一个REST API(以本博客的Api为例子)的方法。

注:

  1. 集成开发环境:IntelliJ Idea 2018.2, 其他也可。
  2. 上线使用LNMP服务器

构建工作空间

已经构建好的就可以跳过这个步骤了。

Golang

官网下载安装文件,遵循 安装指南安装

  • Windows: 默认安装在"c:Go"下, 将"c:Go/in"加入系统环境变量(PATH)即可。
  • Linux: 在VPS服务器上,也需要加入PATH环境变量。

MySQL

  • Windows需安装服务, Linux下直接安装包文件。
  • 数据库管理工具, 有很多可以依据喜好采用(个人在windows下喜欢HeidiSQL)

设置GOPATH并使用Glide进行安装包管理

Glide是一个Golang包管理的增强型工具(类似于javascript中的npm)。 需要将我们的目录设置成如下格式:

- $GOPATH/src/myrestapi (项目名称)
  |
  |-- glide.yaml(包列表, 类似于package.json)
  |
  |-- glide.lock
  |
  |-- main.go (编译入口)
  |
  |-- controller/ (控制器)
  |
  |-- model/  (数据模型)
  |
  |-- middlewares/ (中间件)
  |
  |-- router/ (路由定义)
  |
  |-- test/   (测试)
  |
  |-- vendor/(不需要创建, 自动安装)
       |-- github.com
            |
            |-- Masterminds
                  |
                  |-- ... etc.

在Linux下使用curl https://glide.sh/get | sh进行安装,在Windows下可以下载官方的安装包并将glide.exe加入到PATH环境变量中,这样可以在命令行里使用。 glide会按照glide.yaml文件下的包去安装, 并支持版本的升级。

程序接口及数据定义

这里以一个博客文章的增删改查(CURD)接口作为例子

数据定义

  • 文章: 第一列为一个自增的主键ID, 随后一个是文章的标识
ID         int      `json:"id"`
        PID        string   `json:"pid"`
        PTitle     string   `json:"title"`
        Author     string   `json:"author"`
        Body       string   `json:"body"`
        CreatedAt  int64    `json:"createdAt"`

前台接口

  • GET方法, 取得所有文章列表 /posts
  • GET方法, 取得某一篇文章 /post/:pid

后台管理接口

  • POST方法, 修改某一篇文章 /post.edit
  • POST方法, 删除某一篇文章 /post.delete
  • POST方法, 获取权限(token) /token.get

安装依赖

本例子中需要的依赖如下:

go get github.com/jmoiron/sqlx
    go get github.com/go-sql-driver/mysql
    go get github.com/gin-gonic/gin
    go get github.com/gin-contrib/cors

可选包, 本例利用mongodb的bsonId作为文件的唯一标识, 也可以采用其他方法, 所以安装了这个包。

go get gopkg.in/mgo.v2/bson

glide.yaml文件如下:

package: myrestapi
ignore:
- myrestapi
import:
- package: github.com/gin-gonic/gin
  version: ^1.2.0
- package: github.com/go-sql-driver/mysql
  version: ^1.3.0
- package: github.com/jmoiron/sqlx
- package: gopkg.in/mgo.v2
  subpackages:
  - bson
- package: golang.org/x/sys
  repo: https://github.com/golang/sys.git
  subpackages:
  - unix
- package: golang.org/x/crypto
  repo: https://github.com/golang/crypto.git
  subpackages:
  - bcrypt

并使用glide install安装。

Hello, Gin

以官方的最简单例子稍作变化作为程序的开始, 在主入口文件main.go,

在controller文件夹中新建server.go

package controller

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

func Pong(c *gin.Context) {
    c.JSON(200, gin.H{
        "message": "pong",
    })
}

main.go中引用controller中的函数, 注意函数大写首字母这样才能被外部包访问。

import (
    "myrestapi/controller"
    "github.com/gin-gonic/gin"
)


func main() {
    r := gin.Default()
    r.GET("/ping", controller.Pong)
    r.Run() // 默认为8080端口
}

执行go run main.go并在浏览器里访问localhost:8080/ping, 可以看到{"message":"pong"}

PS: go文件编译后是监听了端口的完整程序。

编写测试用例

由于服务端API功能开发时数据是确定性的, 一个比较好的开发习惯就是测试驱动开发原则(test-driven development, TDD), 先在测试代码辅助下快速完成功能, 然后在测试的保护下重构代码, 确保功能不变。

进入并在test文件夹下新建main_test.go

import  (
  "myrestapi/controller"
    "fmt"
    "net/http"
    "net/http/httptest"
    "testing"
)


func TestMain(m *testing.M) {
    code := m.Run()
    os.Exit(code)
}

func executeRequest(req *http.Request) *httptest.ResponseRecorder {

    rr := httptest.NewRecorder()

    engine := gin.New()

  engine.GET("/ping", controller.Pong)

    engine.ServeHTTP(rr, req)

    return rr
}

// 测试用例1
func TestServerBasic(t *testing.T) {
    req, _ := http.NewRequest("GET", "/ping", nil)
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    response := executeRequest(req)
    fmt.Println(response.Body)
}

执行go test -v, 可以查看返回的数据格式, 也可以使用go test包自带的其他工具验证数据的正确性(因为例子较小自己看速度很快)


未完待续。

0 条评论

评论排序
banner

Tokei

Entertainment & Technical Blog

Bilibili |  Github