欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

golang 如何使用swagger制作项目

程序员文章站 2022-04-03 08:04:37
...

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’
    golang 如何使用swagger制作项目
    golang 如何使用swagger制作项目
    路径存放至 slotSwagger,得到了自动服务器文件夹go-server-server:
    使用ide goland打开,工程起点是slotSwagger:
    golang 如何使用swagger制作项目
    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:aaa@qq.com: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
golang 如何使用swagger制作项目

相关标签: api