As developers, we are already aware of the importance of documenting and organizing all the API’s; but not every developer enjoys the documentation part of the job. The best way to assist us is to use a tool that can automatically prepare API documentation, and Swagger is the ideal tool for this purpose.
What is Swagger?
Swagger is a set of open-source tools built around the OpenAPI Specification that helps us design, build, document, and consume REST APIs.
Why use Swagger?
As we need to follow proper steps in software development, documentation is a ‘must’. With Swagger, we can create API documentation automatically by adding comments to our code and generate REST clients for any technology like Golang, Node, PHP, etc. Swagger is great for maintaining consistent naming conventions, maintaining best practices, and providing a common structure for our applications. Also, it can save coding time on the client side.
In this example, we will develop the API using Golang, and then we will use Swagger to generate the API documentation.
Installing Go-Swagger
The requirement to start this tutorial is to install Go on your local machine. The installation is out of this article’s scope, but the instructions can be easily found on the Internet. Once Go is installed, we can install Go-Swagger as follows:
On the machine, clone the Go-Swagger repo:
git clone https://github.com/go-swagger/go-swagger
Go to the Go-Swagger directory and install it using this command:
go install ./cmd/swagger
To verify that Go-Swagger has been installed, go to cmd and type “swagger” and press ENTER. The output should be as below.
C:\Users\Muhammad_F820>swagger
Please specify one command of: diff, expand, flatten, generate, init, mixin, serve, validate or version.
Implementing Go-Swagger to Golang
Let’s create a new directory named “imp-goswagger” and then open Visual Studio Code. After that, open the terminal and type:
go mod init imp-goswagger
Download dependencies for our project. For this demo we will use:
- Mux: handling http request and routing
go get github.com/gorilla/mux
- Swagger: handling swagger documents
go get github.com/go-openapi/runtime/middleware
- Gorm: handling database transaction
go get gorm.io/gorm
go get gorm.io/driver/postgres
Create a config folder in the root directory. Then create file dbconn.go and write a database connection with the following code:
package database
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/schema"
)
func NewConnectionDB(database string, host string, user string, password string, port int) (*gorm.DB, error) {
var dialect gorm.Dialector
//default singular
gormConfig := &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
}
dsn := fmt.Sprintf(
"host=%s port=%d user=%s dbname=%s password=%s sslmode=%s",
host,
port,
user,
database,
password,
"disable",
)
dialect = postgres.Open(dsn)
db, err := gorm.Open(dialect, gormConfig)
if err != nil {
return nil, err
}
return db, nil
}
Writing Documentation Using Go Swagger
Now that we have created a database connection, the next step is to document using Swagger. It will consist of basic configurations, models, and API Routes.
- Basic Configuration
Place the following code inside main.go.
// Product Api:
// version: 0.1
// title: Product Api
// Schemes: http, https
// Host:
// BasePath: /api/v1
// Consumes:
// - application/json
// Produces:
// - application/json
// SecurityDefinitions:
// Bearer:
// type: apiKey
// name: Authorization
// in: header
// swagger:meta
package main
For security definitions, we use an API key, which can be verified for every API.
- Models
Create models to manage requests and responses of our API. Below are examples of a structure using swagger comments. We can add a name, type, schema, required field, and description for every field.
package model
// swagger:model Product
type Product struct {
// ID of product
// in: int64
ID uint64 `gorm:"primary_key:auto_increment" json:"-"`
// Name of product
// in: string
Name string `json:"name" gorm:"not null;type:varchar"`
// SKU of product
// in: string
SKU string `json:"sku" gorm:"type:varchar"
// UOM of product
// in: string
UOM string `json:"uom" gorm:"type:varchar"`
// Weight of product
// in: int32
Weight int32 `json:"weight"`
}
// swagger:parameters SaveProductRequest
type ReqProductBody struct {
// in: body
Body SaveProductRequest `json:"body"`
}
- API Routes
In this part, we can add swagger comments for every route. We can specify request and response models, route names, request methods, descriptions and API keys if required.
// swagger:operation POST /product Product SaveProductRequest
// Create Product
//
// ---
// responses:
//
// 401: CommonError
// 200: CommonSuccess
func (s *productServiceImpl) CreateProduct(input model.SaveProductRequest) (*model.Product, message.Message) {
s.baseRepo.BeginTx()
product := model.Product{
Name: input.Name,
SKU: input.SKU,
UOM: input.UOM,
Weight: input.Weight,
}
result, err := s.productRepo.Create(&product)
if err != nil {
return nil, message.ErrSaveData
}
return result, message.SuccessMsg
}
// swagger:operation PUT /product/{id} Product SaveProductRequest
// Update Product
//
// ---
// responses:
//
// 401: CommonError
// 200: CommonSuccess
func (s *productServiceImpl) UpdateProduct(id int, input model.SaveProductRequest) (*model.Product, message.Message) {
s.baseRepo.BeginTx()
product, err := s.productRepo.FindById(id)
if err != nil {
return nil, message.ErrNotFound
}
if product != nil {
return nil, message.ErrNotFound
}
product.Name = input.Name
product.SKU = input.SKU
product.UOM = input.UOM
product.Weight = input.Weight
result, err := s.productRepo.Update(id, product)
if err != nil {
return nil, message.ErrSaveData
}
return result, message.SuccessMsg
}
// swagger:operation GET /product/{id} Product byParamGet
// Get Product by Id
//
// ---
// responses:
//
// 401: CommonError
// 200: CommonSuccess
func (s *productServiceImpl) GetProduct(id int) (*model.Product, message.Message) {
s.baseRepo.BeginTx()
result, err := s.productRepo.FindById(id)
if err != nil {
return nil, message.ErrNotFound
}
return result, message.SuccessMsg
}
// swagger:operation GET /product Product getList
// Get Product List
//
// ---
// responses:
//
// 401: CommonError
// 200: CommonSuccess
func (s *productServiceImpl) GetList() ([]model.Product, message.Message) {
s.baseRepo.BeginTx()
results, err := s.productRepo.FindAll()
if err != nil {
return nil, message.ErrNotFound
}
return results, message.SuccessMsg
}
// swagger:operation DELETE /product/{id} Product byParamDelete
// Delete Product by Id
//
// ---
// responses:
//
// 401: CommonError
// 200: CommonSuccess
func (s *productServiceImpl) DeleteProduct(id int) message.Message {
s.baseRepo.BeginTx()
err := s.productRepo.Delete(id)
if err != nil {
return message.ErrDeleteData
}
return message.SuccessMsg
}
After implementing all of the steps above, we can generate swagger yaml or JSON files for swagger comments using this command in the root directory.
swagger generate spec -o ./swagger.yaml –scan-models
It will generate the file swagger.yaml in the root directory. We can add routes to this file for documentation by implementing this code:
pr := mux.NewRouter()
pr.Handle("/swagger.yaml", http.FileServer(http.Dir("./")))
opts := middleware.SwaggerUIOpts{SpecURL: "swagger.yaml"}
sh := middleware.SwaggerUI(opts, nil)
pr.Handle("/docs", sh)
//// documentation for share
opts1 := middleware.RedocOpts{SpecURL: "swagger.yaml", Path: "doc"}
sh1 := middleware.Redoc(opts1, nil)
pr.Handle("/doc", sh1)
Finally, we can run our apps and open this URL to see the documentation.

So, those are the steps to create Golang API Documentation using Go Swagger. For the complete code, visit the GitHub repository: imp-goswagger
Final Thoughts
Effective documentation has been proven to enhance productivity, as shown by GitHub’s 2021 State of the Octoverse report, which revealed a 50% productivity boost for developers when easy-to-source documentation was available. This increase in productivity alone makes a compelling case for the value of documentation, but just in case, we’ll add a few more.
Well-written documentation contributes to building strong team cultures.
GitHub’s report highlights the importance of good information flow in building trust and promoting developer satisfaction, particularly in remote work environments where teams work from different locations. Documentation plays a crucial role in ensuring that knowledge is shared amongst team members – both current and future.
Code documentation is essential for onboarding new developers.
For developers, an important part of the onboarding process includes a tour of the existing codebase. It also involves an overview of the system architecture and an introduction to team coding practices and conventions. Using Swagger makes this process transparent and sustainable even if there is high turnover on a team.
Hopefully, this article has been informative and will help implement documentation on our Golang API, since documentation is critical for developers.
References:
https://www.infoq.com/articles/design-first-api-development/
https://www.postman.com/state-of-api/api-first-strategies/
https://www.bacancytechnology.com/blog/create-golang-api-documentation-using-go-swagger
Author: Muhammad Farisul Khilmi, Software Engineer Programmer