golang 如何使用swagger制作项目

swagger是一款绿色开源的后端工具,以yml或者json格式的说明文档为基点,包含了以此说明文档一站式自动生成后端(路由转发层)代码、api说明文档spec可视化,客户端与交互模型client and model自动生成等模块。本文主要从安装本地swagger editor 到 一键生成 server端,并自制client测试对象slot的增删改查。阅读本文的读者须有基本的go语法与http协议知识.

  1. 安装swagger editor
    https://swagger.io/ 官网安装下载swagger editor,解压后从cmd进入该解压文件路径,执行:
    npm install -g
    npm start
    使用npm的前提是要配置号nodeJS的环境,这里不再赘述
    执行完后,cmd窗口上,会显示出服务的url地址,在任意浏览器地址栏上输入即可进入本地swagger editor,其内容和在线版本基本完全一致,所以网络环境健康的读者可以跳过第一步
    http://editor.swagger.io/ 在线editor

  2. 编辑slot.yml文档
    yml的语法糖在这里有介绍https://legacy.gitbook.com/book/huangwenchao/swagger/details

swagger: "2.0"
info:
  description: A slot crud apis
  title: Basic swagger example application
  version: 1.0.0
consumes:
- application/io.goswagger.examples.todo-list.v1+json
- application/json
produces:
- application/io.goswagger.examples.todo-list.v1+json
- application/json
schemes:
- http
paths:
  /slots/list:
    get:
      operationId: GetAll
      description: Gets some slots
      responses: 
        200:
          description: returns slot list of all
          schema:
            $ref: "#/definitions/Slots"
  /slot/add:
    post:
      operationId: addOne
      description: new a slot
      parameters:
        - name: slot_name
          in: body
          description: new a slot
          schema:
            required:
              - slot_name
            properties:
              slot_name:
                type: string
      responses: 
        200:
          description: returns a msg
          schema:
              required:
                - msg
              properties:
                msg:
                  type: string
  /slot/modify:
    post:
      operationId: modifySlot
      description: modify a slot name by given id
      parameters:
        - name: slot_id
          in: body
          description: use slot_id to locate a slot
          schema:
            required:
              - slot_id
            properties:
              slot_id:
                type: string
      responses:
        200:
          description: success modify a slot
          schema:
            required:
              - msg
            properties:
              msg:
                type: string
  /slot/delete:
    post:
      operationId: deleteSlot
      description: delete a slot name by given id
      parameters:
        - name: slot_id
          in: body
          description: use slot_id to locate a slot
          schema:
            required:
              - slot_id
            properties:
              slot_id:
                type: string
      responses:
        200:
          description: success delete a slot
          schema:
            required:
              - msg
            properties:
              msg:
                type: string

definitions:
  Slot:
    required:
      - slot_name
    properties:
      id:
        type: integer
      slot_name:
        type: string
  Slots:
    type: array
    items:
      $ref: "#/definitions/Slot"
  1. 该文档描述了slot的增删改查开放的api接口,新建文件夹slotSwagger,点击editor的’generate server’-‘go server’
    这里写图片描述
    这里写图片描述
    路径存放至 slotSwagger,得到了自动服务器文件夹go-server-server:
    使用ide goland打开,工程起点是slotSwagger:
    这里写图片描述
    4.至此swagger的一键路由层做好了,喜欢研究的人可以都点进去看看,其实我们只关注./go/default_api.go
    接下来来把这项工程做完整一点。
    数据库postgresql:
    CREATE TABLE slot
(
  id serial primary key,
  name varchar(20)
);

insert into slot(name) values('广告位1');

default_api.go

/*
 * Basic swagger example application
 *
 * A slot crud apis
 *
 * API version: 1.0.0
 * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
 */

package swagger

import (
    "net/http"
    db "github.com/fwhezfwhez/xorm-tool"
    "encoding/json"
    "io/ioutil"
    "fmt"
    "strings"
    "errors"
    "swaggerSlot/go-server-server/models"
)

func init() {
    db.DataSource("postgres://postgres:123@localhost:5432/test?sslmode=disable")
    db.DefaultConfig()
}
func AddOne(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    type SlotAdd struct{
        SlotName string `json:"slot_name"`
    }
    slot:= SlotAdd{}
    err:= Bind(&slot,r)
    fmt.Println("获取到slotName:",slot.SlotName)
    if err!=nil{
        w.WriteHeader(200)
        fmt.Fprint(w,err.Error())
        return
    }
    _,er:=db.Insert("insert into slot(name) values(?)",slot.SlotName)
    if er!=nil{
        w.WriteHeader(200)
        fmt.Fprint(w,err.Error())
        return
    }
    w.WriteHeader(http.StatusOK)
    fmt.Fprint(w,"成功新增")
}

func DeleteSlot(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    type SlotDelete struct{
        SlotId string `json:"slot_id"`
    }
    slot:= SlotDelete{}
    err:= Bind(&slot,r)
    fmt.Println("获取到slotId:",slot.SlotId)
    if err!=nil{
        w.WriteHeader(200)
        fmt.Fprint(w,err.Error())
        return
    }

    _,er:=db.Delete("delete from slot where id=?",slot.SlotId)
    if err!=nil{
        w.WriteHeader(200)
        fmt.Fprint(w,er.Error())
        return
    }
    w.WriteHeader(http.StatusOK)
    fmt.Fprint(w,"成功删除")
}

func GetAll(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    slots :=make([]models.Slot,0)
    err:=db.Select(&slots,"select * from slot")
    if err !=nil{
        w.WriteHeader(http.StatusOK)
        fmt.Fprint(w,err.Error())
        return
    }

    w.WriteHeader(http.StatusOK)
    fmt.Fprint(w,slots)
}

func ModifySlot(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    type SlotModify struct{
        SlotId string `json:"slot_id"`
    }
    slot:=SlotModify{}
    err:=Bind(&slot,r)
    if err!=nil{
        w.WriteHeader(200)
        fmt.Fprint(w,err.Error())
        return
    }
    _,err=db.Update("update slot set name='modified' where id=?",slot.SlotId)
    if err!=nil{
        w.WriteHeader(200)
        fmt.Fprint(w,err.Error())
        return
    }
    w.WriteHeader(http.StatusOK)
    fmt.Fprint(w,"成功修改")
}

func Bind(dest interface{},r *http.Request) error{
    rMethod := strings.ToUpper(r.Method)
    if rMethod=="POST"||rMethod=="PATCH"||rMethod=="PUT"||rMethod=="DELETE" {
        body,err:=ioutil.ReadAll(r.Body)
        defer r.Body.Close()
        if err!=nil {
            return err
        }
        if r.Header.Get("Content-Type") =="application/json"{
            err:=json.Unmarshal(body,dest)
            if err!=nil{
                return err
            }
        }
        return nil
    }else if rMethod=="GET"{
        return errors.New("not implemented")
    }else{
        return errors.New("method should be one of [GET,POST,PATCH,DELETE,PUT]")
    }
}

客户端:

package main

import (
    "encoding/json"
    "net/http"
    "bytes"
    "fmt"
    "io/ioutil"
)

type Slot struct{
    SlotId string `json:"slot_id,omitempty"`
    SlotName string `json:"slot_name,omitempty"`
}
func main() {
    TestAdd()
    TestUpdate()
    TestQuery()
    TestDelete()
}

func TestAdd(){
    slot:= Slot{SlotName:"广告位2"}
    adddJson,err:=json.Marshal(slot)
    if err!=nil{
        panic(err)
    }
    resp, err := http.Post("http://localhost/slot/add", "application/json", bytes.NewReader(adddJson))
    defer resp.Body.Close()
    if err!=nil{
        panic(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

func TestDelete(){
    slot:= Slot{SlotId:"2"}
    adddJson,err:=json.Marshal(slot)
    if err!=nil{
        panic(err)
    }
    resp, err := http.Post("http://localhost:8080/slot/delete", "application/json", bytes.NewReader(adddJson))
    defer resp.Body.Close()
    if err!=nil{
        panic(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

func TestUpdate(){
    slot:= Slot{SlotId:"3"}
    adddJson,err:=json.Marshal(slot)
    if err!=nil{
        panic(err)
    }
    resp, err := http.Post("http://localhost:8080/slot/modify", "application/json", bytes.NewReader(adddJson))
    defer resp.Body.Close()
    if err!=nil{
        panic(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}
func TestQuery(){
    resp, err := http.Get("http://localhost:8080/slots/list")
    defer resp.Body.Close()
    if err!=nil{
        panic(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

result

成功新增
成功修改
[{1 广告位1} {4 广告位2} {3 modified}]
成功删除

自动生成的api说明文档是这样的,目前没有把该项目部署到网上,说明文档的实例这里就有现成的:
http://editor.swagger.io/
slot微项目托管地址:https://github.com/fwhezfwhez/items/tree/master/swaggerSlot
这里写图片描述

猜你喜欢

转载自blog.csdn.net/fwhezfwhez/article/details/80260134
今日推荐