GO/Gin gin-swagger使用してAPI仕様書を生成します


# 前書

この記事は `gin-swagger`ライブラリ使用してGinプロダクトにAPI仕様書生成するための知見をまとめるものになります。
[gin-swaggerリポジトリリンク](https://github.com/swaggo/gin-swagger)
![swagger-banner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/462bd1f0-1756-44a5-7363-f88e6553281c.png)


# テスト用のプロダクトを作成
フォルダを作成

```
// 任意のディレクトリで
$ mkdir use_swagger && cd use_swagger
```
go modを初期化

```
$ go mod init use_swagger
```

# ライブラリインストール

```
$ go get -u github.com/gin-gonic/gin
$ go get -u github.com/swaggo/swag/cmd/swag
$ go get -u github.com/swaggo/gin-swagger
$ go get -u github.com/swaggo/files
```
インストール完了後のバージョン確認。

```
$ swag -v
swag version v1.6.7
```
現在のディレクトリ構成

```
|-- use_swagger
|-- |-- go.mod
```

# プロダクトにAPI仕様書追加

`use_swagger`ディレクトリ配下に`main.go`ファイル作成

```
$ touch main.go
```

追加前

```go:main.go
package main

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

func main() {
	r := gin.New()	
	r.GET("/test", test)	
	r.Run()
}

func test(c *gin.Context){
	c.JSON(http.StatusOK, gin.H{ "msg": "ok"})
}

```
サーバー立ち上げ後 `http://localhost:8080/test`にアクセスすると、簡単なJsonデータが戻ってきます。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/25d27199-b706-2d1d-b529-e7ed7cd3e0af.png)

追加後

```go:main.go
package main

import (
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	"github.com/swaggo/gin-swagger"
	"net/http"

	_ "use_swagger/docs"
)

// @title APIドキュメントのタイトル
// @version バージョン(1.0)
// @description 仕様書に関する内容説明
// @termsOfService 仕様書使用する際の注意事項

// @contact.name APIサポーター
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io

// @license.name ライセンス(必須)
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host localhost:8080
// @BasePath /
func main() {
	r := gin.New()

	url := ginSwagger.URL("http://localhost:8080/swagger/doc.json")
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
	
	r.GET("/test", test)
	r.Run()
}

// @description テスト用APIの詳細
// @version 1.0
// @accept application/x-json-stream
// @param none query string false "必須ではありません。"
// @Success 200 {object} gin.H {"code":200,"msg":"ok"}
// @router /test/ [get]
func test(c *gin.Context){
	c.JSON(http.StatusOK, gin.H{ "msg": "ok"})
}
```
仕様書を初期化します。

```
$ swag init
```
初期化完了後、ディレクトリ構成は以下のようになりました。

```
|-- use_swagger
|-- |-- docs
|-- |-- |-- docs.go
|-- |-- |-- swagger.json
|-- |-- |-- swagger.yaml
|-- |-- main.go
|-- |-- go.mod
```
サーバーを立ち上げ、`http://localhost:8080/swagger/index.html`へアクセスすれば、仕様書が表示されます。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/7dff5498-77f5-ec55-440e-f1bfa9cf8dc1.png)
実際使ってみます、適当にパラメータを渡して、実行します。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/6cf9c6bc-f27f-81c4-a8b8-43b9596f4815.png)
期待通りのレスポンスが返ってきました。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/f3bccc16-dab8-93be-6820-961c5ba9f784.png)

# よく使用されるオプション

## API オプション
|    オプション|   説明                                  |
|:-----------:|:--------------------------------------:|
| description |          操作動作の詳細な説明。                              |
| id          |操作を識別するために使用される一意の文字列。すべてのAPI操作の中で一意である必要があります。(使用されてる所あんまり見ない) |
| tags        | コンマで区切られた各API操作へのタグのリスト、APIの関連性を示します。        |
| summary     | 操作の実行内容の簡単な要約。  |
| accept      |  APIが使用できる[MIMEヘッダタイプ](https://ja.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions)のリスト。値は、[MIMEヘッダタイプ](https://swaggo.github.io/swaggo.io/declarative_comments_format/api_operation.html#mime-types)で説明されているとおりでなければなりません。  |
|produce      | APIが生成できるMIMEタイプのリスト。値は、[MIMEヘッダタイプ](https://swaggo.github.io/swaggo.io/declarative_comments_format/api_operation.html#mime-types)で説明されているとおりでなければなりません。|
|param         | スペースで区切られたパラメーター。パラメータ名、パラメータタイプ、データタイプ、必須ですか？、コメント属性（オプション）|
| security| 各API操作のセキュリティ。|
|  success| スペースで区切られた成功レスポンス。レスポンスコード、{param type}、データ型、コメント|
| failure | スペースで区切られた障害レスポンス。レスポンスコード、{param type}、データ型、コメント|
| router  | パス、[httpMethod]|

### 使用凡例
```go
// @Summary Auth admin
// @Description get admin info
// @Tags accounts,admin
// @Accept  application/x-json-stream
// @Produce  application/x-json-stream
// @Success 200 {object} model.Admin
// @Failure 400 {object} httputil.HTTPError
// @Failure 401 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPError
// @Security ApiKeyAuth
// @Router /admin/auth [post]
func (c *Controller) Auth(ctx *gin.Context) {
	authHeader := ctx.GetHeader("Authorization")
	if len(authHeader) == 0 {
		httputil.NewError(ctx, http.StatusBadRequest, errors.New("please set Header Authorization"))
		return
	}
	if authHeader != "admin" {
		httputil.NewError(ctx, http.StatusUnauthorized, fmt.Errorf("this user isn't authorized to operation key=%s expected=admin", authHeader))
		return
	}
	admin := model.Admin{
		ID:   1,
		Name: "admin",
	}
	ctx.JSON(http.StatusOK, admin)
}
```

```go
// ShowBottle godoc
// @Summary Show a bottle
// @Description get string by ID
// @ID get-string-by-int
// @Tags bottles
// @Accept  json
// @Produce  json
// @Param  id path int true "Bottle ID"
// @Success 200 {object} model.Bottle
// @Failure 400 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPError
// @Router /bottles/{id} [get]
func (c *Controller) ShowBottle(ctx *gin.Context) {
	id := ctx.Param("id")
	bid, err := strconv.Atoi(id)
	if err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	bottle, err := model.BottleOne(bid)
	if err != nil {
		httputil.NewError(ctx, http.StatusNotFound, err)
		return
	}
	ctx.JSON(http.StatusOK, bottle)
}
```


その他API情報は[公式ドキュメント](https://swaggo.github.io/swaggo.io/declarative_comments_format/general_api_info.html)と[こちらのリポジトリ](https://github.com/swaggo/swag/tree/master/example/celler/controller)を参考にしてください。




# 使用感想
gin-swaggerライブラリは非常に便利とは言えない、コメントから生成されるAPI仕様書であるために、
記述する際には間違えがないかよく確認したほうがいいと思います。:point_up_tone1: