博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用go-swagger为golang API自动生成swagger文档
阅读量:5844 次
发布时间:2019-06-18

本文共 5863 字,大约阅读时间需要 19 分钟。

什么是swagger?

是一个简单但功能强大的API表达工具。它具有地球上最大的API工具生态系统,数以千计的开发人员,使用几乎所有的现代编程语言,都在支持和使用Swagger。使用Swagger生成API,我们可以得到交互式文档,自动生成代码的SDK以及API的发现特性等。

swagger文档长啥样?

一个最简单的swagger文档示例:

swagger: "2.0"info:  version: 1.0.0  title: Simple API  description: A simple API to learn how to write OpenAPI Specificationschemes:  - httpshost: simple.apibasePath: /openapi101paths: {}复制代码

Tips:阅读本文前提是假设你已经了解了如何编写swagger文档,当然,如果还不了解也没关系,可以去查看文档进行学习,并且这里还有一套附上.

本文背景介绍

​ 写作本文的原因是因为公司要求api文档都使用 swagger格式,项目是用golang编写的,作为一个懒癌程序员,怎么能够忍受去编写这么复杂的swagger文档呢?有没有一键生成的工具呢?google一下,还真有,那就是项目。go-swagger众多特色功能之一就是,即通过源码生成文档,很符合我的需求。

下面就简单介绍下如何为项目加上swagger注释,然后一键生成API文档

开始之前需要安装两个工具:

  • swagger-editor:用于编写swagger文档,UI展示,生成代码等...
  • go-swagger:用于一键生成API文档

安装swagger-editor,我这里使用docker运行,其他安装方式,请查看:

docker pull swaggerapi/swagger-editordocker run --rm -p 80:8080 swaggerapi/swagger-editor复制代码

安装go-swagger,我这边使用brew安装,其他安装方式,请查看

brew tap go-swagger/go-swaggerbrew install go-swagger复制代码

好了,现在终于开始正题:start coding!!!

开始编写注释

1.假设有一个user.server,提供一些REST API,用于对用户数据的增删改查。

比如这里有一个getOneUser接口,是查询用户信息的:

package serviceimport (    "encoding/json"    "fmt"    "net/http"    "strconv"    "user.server/models"    "github.com/Sirupsen/logrus")type GetUserParam struct {    Id int `json:"id"`}func GetOneUser(w http.ResponseWriter, r *http.Request) {    defer r.Body.Close()    decoder := json.NewDecoder(r.Body)    var param GetUserParam    err := decoder.Decode(&param)    if err != nil {        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)        return    }    // get user from db    user, err := models.GetOne(strconv.Itoa(param.Id))    if err != nil {        logrus.Warn(err)        WriteResponse(w, ErrorResponseCode, "failed", nil)        return    }    WriteResponse(w, SuccessResponseCode, "success", user)}复制代码

根据swagger文档规范,一个swagger文档首先要有swagger的版本和info信息。利用go-swagger只需要在声明package之前加上如下注释即可:

// Package classification User API.//// The purpose of this service is to provide an application// that is using plain go code to define an API////      Host: localhost//      Version: 0.0.1//// swagger:metapackage service复制代码

然后在项目根目录下使用swagger generate spec -o ./swagger.json命令生成swagger.json文件:

此命令会找到main.go入口文件,然后遍历所有源码文件,解析然后生成swagger.json文件

{  "swagger": "2.0",  "info": {    "description": "The purpose of this service is to provide an application\nthat is using plain go code to define an API",    "title": "User API.",    "version": "0.0.1"  },  "host": "localhost",  "paths": {}}复制代码

2.基本信息有了,然后就要有路由,请求,响应等,下面针对getOneUser接口编写swagger注释:

// swagger:parameters getSingleUsertype GetUserParam struct {    // an id of user info    //    // Required: true    // in: path    Id int `json:"id"`}func GetOneUser(w http.ResponseWriter, r *http.Request) {    // swagger:route GET /users/{id} users getSingleUser    //    // get a user by userID    //    // This will show a user info    //    //     Responses:    //       200: UserResponse    decoder := json.NewDecoder(r.Body)    var param GetUserParam    err := decoder.Decode(&param)    if err != nil {        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)        return    }    // get user from db    user, err := models.GetOne(strconv.Itoa(param.Id))    if err != nil {        logrus.Warn(err)        WriteResponse(w, ErrorResponseCode, "failed", nil)        return    }    WriteResponse(w, SuccessResponseCode, "success", user)}复制代码

可以看到在GetUserParam结构体上面加了一行swagger:parameters getSingleUser的注释信息,这是声明接口的入参注释,结构体内部的几行注释指明了id这个参数必填,并且查询参数id是在url path中。详细用法,参考:

GetOneUser函数中:

  • swagger:route指明使用的http method,路由,以及标签和operation id,详细用法,参考:
  • Responses指明了返回值的code以及类型

然后再声明响应:

// User Info//// swagger:response UserResponsetype UserWapper struct {    // in: body    Body ResponseMessage}type ResponseMessage struct {    Code    int         `json:"code"`    Message string      `json:"message"`    Data    interface{} `json:"data"`}复制代码

使用swagger:response语法声明返回值,其上两行是返回值的描述(我也不清楚,为啥描述信息要写在上面,欢迎解惑),详细用法,参考;

然后浏览器访问localhost,查看swagger-editor界面,点击工具栏中的File->Impoprt File上传刚才生成的 swagger.json文件,就可以看到界面:

这样一个简单的api文档就生成了

3.怎么样?是不是很简单?可是又感觉那里不对,嗯,注释都写在代码里了,很不美观,而且不易维护。想一下go-swagger的原理是扫描目录下的所有go文件,解析注释信息。那么是不是可以把api注释都集中写在单个文件内,统一管理,免得分散在各个源码文件内。

新建一个doc.go文件,这里还有一个接口是UpdateUser,那么我们在doc.go文件中声明此接口的api注释。先看一下UpdateUser接口的代码:

func UpdateUser(w http.ResponseWriter, r *http.Request) {    defer r.Body.Close()    // decode body data into user struct    decoder := json.NewDecoder(r.Body)    user := models.User{}    err := decoder.Decode(&user)    if err != nil {        WriteResponse(w, ErrorResponseCode, "user data is invalid, please check!", nil)        return    }    // check if user exists    data, err := models.GetUserById(user.Id)    if err != nil {        logrus.Warn(err)        WriteResponse(w, ErrorResponseCode, "query user failed", nil)        return    }    if data.Id == 0 {        WriteResponse(w, ErrorResponseCode, "user not exists, no need to update", nil)        return    }    // update    _, err = models.Update(user)    if err != nil {        WriteResponse(w, ErrorResponseCode, "update user data failed, please try again!", nil)        return    }    WriteResponse(w, SuccessResponseCode, "update user data success!", nil)}复制代码

然后再doc.go文件中编写如下声明:

package serviceimport "user.server/models"// swagger:parameters UpdateUserResponseWrappertype UpdateUserRequest struct {    // in: body    Body models.User}// Update User Info//// swagger:response UpdateUserResponseWrappertype UpdateUserResponseWrapper struct {    // in: body    Body ResponseMessage}// swagger:route POST /users users UpdateUserResponseWrapper//// Update User//// This will update user info////     Responses://       200: UpdateUserResponseWrapper复制代码

这样就把api声明注释给抽离出来了,然后使用命令swagger generate spec -o ./swagger.json生成json文件,就可以看到这样的结果:

很简单吧,参照文档编写几行注释,然后一个命令生成API文档。懒癌程序员福音~

本文所有示例代码托管在, 原文

参考:

转载地址:http://yshcx.baihongyu.com/

你可能感兴趣的文章
NgDL:第三周:浅层NN
查看>>
Flask第十八篇 Flask-Migrate
查看>>
ETL-informatica进阶资料整理
查看>>
注册使用GAC【转载】
查看>>
leetcode41
查看>>
用技术——设计模式22——行为型模式——模板模式——待补充
查看>>
虚伪杂谈
查看>>
vue 创建全局组件三种方式
查看>>
PHP获取本月当月,起始结束日期
查看>>
mysql保存中文乱码的原因和解决办法
查看>>
深入.NET框架
查看>>
webgote的例子(5)Sql注入(Blog)
查看>>
[ASP.NET AJAX]How to register javascript functions after UpdatePanel updated
查看>>
AC日记——【模板】二分图匹配 洛谷 P3386
查看>>
AC日记——计算循环节长度 51nod 1035
查看>>
AC日记——Sagheer, the Hausmeister codeforces 812b
查看>>
比特币交易构成
查看>>
Android倒计时器——CountDownTimer
查看>>
java poi 读取Excel中的手机号
查看>>
C++11 pair的使用
查看>>