Tutorial: Generate Swagger Specification and SwaggerUI for Gin Go Web Framework

Rizal Widyarta Gowandy
Level Up Coding
Published in
5 min readApr 15, 2021

--

Why Gin Web Framework?

Gin is one of the most popular frameworks for Go. It’s simple to use.

Why Swagger Specification?

Writing a specification is a meticulous process in Software Engineering. Regardless, it’s necessary if we want our API being used by others. It helps others to integrate without API with more ease. The better the documentation the easier others will integrate it into their system. In order to tackle this problem, we should follow a standardized way to create API documentation in the industry, the OpenAPI Specification or formerly known as the Swagger Specification.

The OpenAPI Specification, formerly known as the Swagger Specification, is the world’s standard for defining RESTful interfaces. The OAS enables developers to design a technology-agnostic API interface that forms the basis of their API development and consumption.

Prerequisite

You need to install Go version ≥1.14 in your machine.

Steps

  1. Create folders for development, we will call the app ginsimple.
$ mkdir ginsimple
$ mkdir docs
$ mkdir docs/ginsimple

2. Initialize go mod for go vendor system.

$ go mod init

3. Pull the Gin library.

$ go get -u github.com/gin-gonic/gin

4. Inside ginsimple folder, create a new file main.go and copy the code below.

package main

import (
"log"
"net/http"

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

func main() {
// Gin instance
r := gin.New()

// Routes
r.GET("/", HealthCheck)

// Start server
if err := r.Run(":3000"); err != nil {
log.Fatal(err)
}
}

func HealthCheck(c *gin.Context) {
res := map[string]interface{}{
"data": "Server is up and running",
}

c.JSON(http.StatusOK, res)
}

5. Run the app.

$ go run ginsimple/main.go

You should see an output like below.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. 
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET / --> main.HealthCheck (1 handlers)
[GIN-debug] Listening and serving HTTP on :3000

It means our server is up and running on port 3000.

6. Update our main.go by adding declarative comments format. These comments will be used later to automatically generate Swagger Specification. You can learn more about the declarative comments format using the link in the reference.

package main

import (
"log"
"net/http"

"github.com/gin-gonic/gin"
)
// @title Gin Swagger Example API
// @version 1.0
// @description This is a sample server server.
// @termsOfService http://swagger.io/terms/

// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host localhost:3000
// @BasePath /
// @schemes http
func main() {
// Gin instance
r := gin.New()

// Routes
r.GET("/", HealthCheck)

// Start server
if err := r.Run(":3000"); err != nil {
log.Fatal(err)
}
}
// HealthCheck godoc
// @Summary Show the status of server.
// @Description get the status of server.
// @Tags root
// @Accept */*
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Router / [get]
func HealthCheck(c *gin.Context) {
res := map[string]interface{}{
"data": "Server is up and running",
}

c.JSON(http.StatusOK, res)
}

7. Pull swagger libraries.

$ go get -v github.com/swaggo/swag/cmd/swag
$ go get -v github.com/swaggo/gin-swagger
$ go get -v github.com/swaggo/files

8. Generate the Swagger Specification.

$ swag init -g ginsimple/main.go --output docs/ginsimple

If the operation is successful, you should see 3 new files inside folder docs/ginsimple. These files are:

  • docs.go => Requires to generate SwaggerUI.
  • swagger.json => The Swagger Specification in json file format.
  • swagger.yaml => The Swagger Specification in yaml file format.

If you use Confluence to distribute your documentation, you could create a new file inside Confluence and choose to add OpenAPI Specification. Then copy and paste the swagger.yaml content inside.

9. Update main.go to add SwaggerUI.

package main

import (
"log"
"net/http"

"github.com/gin-gonic/gin"
_ "github.com/rizalgowandy/go-swag-sample/docs/ginsimple" // you need to update github.com/rizalgowandy/go-swag-sample with your own project path
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)

// @title Gin Swagger Example API
// @version 2.0
// @description This is a sample server server.
// @termsOfService http://swagger.io/terms/

// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host localhost:3000
// @BasePath /
// @schemes http
func main() {
// Gin instance
r := gin.New()

// Routes
r.GET("/", HealthCheck)

url := ginSwagger.URL("http://localhost:3000/swagger/doc.json") // The url pointing to API definition
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))

// Start server
if err := r.Run(":3000"); err != nil {
log.Fatal(err)
}
}

// HealthCheck godoc
// @Summary Show the status of server.
// @Description get the status of server.
// @Tags root
// @Accept */*
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Router / [get]
func HealthCheck(c *gin.Context) {
res := map[string]interface{}{
"data": "Server is up and running",
}

c.JSON(http.StatusOK, res)
}

As you can see, there are 2 important things we add on our main.go.

  • A new route for SwaggerUI.
url := ginSwagger.URL("http://localhost:3000/swagger/doc.json") // The url pointing to API definition
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
  • New imports for the generated docs.go and swag library. Don’t forget to replace the github.com/rizalgowandy/go-swag-sample path with your project path.
import (
...
_ "github.com/rizalgowandy/go-swag-sample/docs/ginsimple" // you need to update github.com/rizalgowandy/go-swag-sample with your own project path
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
...
)

10. Finally, run the app again.

$ go run ginsimple/main.go

11. Now try, the call the newly added route.

$ curl localhost:3000/swagger/doc.json

You should see output like.

// 20210415135919
// http://localhost:3000/swagger/doc.json
{
"schemes": [
"http"
],
"swagger": "2.0",
"info": {
"description": "This is a sample server server.",
"title": "Gin Swagger Example API",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "API Support",
"url": "http://www.swagger.io/support",
"email": "support@swagger.io"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "2.0"
},
"host": "localhost:3000",
"basePath": "/",
"paths": {
"/": {
"get": {
"description": "get the status of server.",
"consumes": [
"*/*"
],
"produces": [
"application/json"
],
"tags": [
"root"
],
"summary": "Show the status of server.",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}

12. Open the SwaggerUI in the browser using this URL.

http://localhost:3000/swagger/index.html

You should see output like.

OpenAPI Specification UI

Voilà, and we are done. We successfully created a simple Go web server using Gin framework, and generate the Swagger Specification and SwaggerUI.

References

--

--

Software Engineer | INTJ | Choleric | The Questioner (CD) | Creator & Advisor