To help you auto generate swagger for your golang APIs
<a href="https://github.com/diegoclair/goswag/tags" alt="GitHub tag">
<img src="https://img.shields.io/github/tag/diegoclair/goswag.svg" />
</a>
<a href='https://coveralls.io/github/diegoclair/goswag?branch=main'>
<img src='https://coveralls.io/repos/github/diegoclair/goswag/badge.svg?branch=main' alt='Coverage Status' />
</a>
<a href="https://github.com/diegoclair/goswag/actions">
<img src="https://github.com/diegoclair/goswag/actions/workflows/ci.yaml/badge.svg" alt="build status">
</a>
<a href="https://github.com/diegoclair/goswag/contributors" alt="Contributors">
<img src="https://img.shields.io/github/contributors/diegoclair/goswag" />
</a>
<a href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" />
</a>
<a href='https://goreportcard.com/badge/github.com/diegoclair/goswag'>
<img src='https://goreportcard.com/badge/github.com/diegoclair/goswag' alt='Go Report'/>
</a>
It will extend your Go framework by providing methods to generate a separate file containing all the necessary comments. These comments enable the Swag library to effortlessly generate Swagger files.
I was searching for an automated method to generate Swagger documentation for Golang APIs. I came across the swaggo/swag lib, which seems to be the most popular choice or, at the very least, has numerous articles and tutorials promoting its use. However, I was dissatisfied with the process of adding extensive comments throughout the main file and other files containing handler functions. As a result, I decided to develop the goswag library.
Goswag simplifies the process of integrating Swagger documentation generation into your Go projects. By seamlessly aligning with your chosen framework's usage patterns, Goswag ensures a smooth integration experience.
For instance, if your framework uses a POST method with specific parameters, Goswag mirrors these method and parameters, streamlining the integration process. This principle applies across supported frameworks, ensuring consistency and ease of use.
Write this:
Instead of this:
And will have the same result:

When initializing your current framework, such as e := echo.New(), begin by replacing it with ge := goswag.NewEcho() or gg := goswag.NewGin(gin) by passing the Gin instance as a parameter for the Gin framework.
If you intend to utilize the framework with alternative configurations, for instance: e.Debug = true, you can access e as follows: ge.Echo().Debug = true achieving identical results.
After completing the initial setup, your routes are established without errors and require no further changes. However, your routes will now possess additional methods:
- Summary: Provides a brief overview of your route.
- Description: Offers a detailed description of your route (If not set, it defaults to the summary).
- Accepts: The default value is json. f you wish to incorporate different values, please refer to the list of possible values here.
- Produces: The default value is json. To include different values, consult the list of possible options here.
- Read: ISpecifies the request body received by your routes.
- Returns: Is an array of ReturnType{}. Your route can have multiples returns (e.g., success, errors e etc). Refer to the interface reference for detailed usage information.
type ReturnType struct {
StatusCode int
Body any
// example: map[jsonFieldName]fieldType{}
OverrideStructFields map[string]any
}
QueryParam: Defines the query parameters of the route and specifies if they are required.HeaderParam: Defines the header parameters of the route and specifies if they are required.PathParam: Defines the path parameters of the route and specifies if they are required.The method used to instantiate your router, either NewEcho() or NewGin() includes a function called GenerateSwagger().
After setting up all your routes (including annotations), you can invoke GenerateSwagger() to generate your swagger documentation. However, this implies that if your route setup relies on services like a running database or RabbitMQ, you can only generate your Swagger documentation when your entire infrastructure is operational, which is not ideal.
The recommended approach is to have a separate main file where you do not need to provide real connections for your route setup.
Consider a file named server.go with the following setup:
func SetupRoutes(db *sql.DB) *echo.Echo {
e := echo.New()
handlers := handlers.New(db)
e.GET("/hello", handlers.HandleHello)
return e
}
In order to start your router, you currently need to provide a database connection. However, this requirement is unnecessary for generating Swagger documentation.
goswag.goswag folder, create a file called main.go with package main.// @title GoSwag example API
// @version 1.0
func main() {
// Here you have already used goswag for your route setup, added annotations and change it return to goswag.Echo or Gin interfaces
ge := server.SetupRoutes(nil)
ge.GenerateSwagger() //will generate your swagger
}
Install the goswag CLI once:
go install github.com/diegoclair/goswag/cmd/goswag@latest
Then, from your project root, run:
goswag docs
That single command:
1. Runs go run ./goswag/main.go (generates the annotated stub).
2. Runs swag init --pdl=<auto> --parseInternal -g ./goswag/main.go -o ./docs.
3. Runs swag fmt -d ./goswag/.
swag is installed automatically if it is not on your PATH.
--pdlgoswag docs picks --pdl for you by inspecting the imports of the generated stub: 0 if every type comes from your module, 1 if any annotation references a type from an external dependency. The chosen level is printed on each run. Override with --pdl=N if you need 2 or 3 (rare).
All paths follow the convention described above; override them with flags if your layout differs:
goswag docs --input ./goswag --output ./docs
# or, with shorthands:
goswag docs -i ./goswag -o ./docs
Run goswag docs --help for the full list of flags.
If you want a project-local entry point, a Makefile target is just:
.PHONY: docs
docs:
@goswag docs
The command produces a goswag.go file inside your goswag directory containing all handler stubs and annotations, and the OpenAPI files under ./docs.
NOTE: after the first generation, the doc.go file in the docs folder will import the Swag library. If you haven't used Swag in your project before, run go mod tidy to ensure the swag package is included in your go.mod.
go install github.com/diegoclair/goswag/cmd/goswag@latestgo get -u github.com/diegoclair/goswag && go mod tidyYou can add a default responses to all routes when you instantiate the swagger.
To add default responses, you need to define your list of default returns and add it to instance, ex:
defaultResponses := []models.ReturnType{
{
StatusCode: http.StatusBadRequest,
Body: YourStructOfError,
},
{
StatusCode: http.StatusUnauthorized,
Body: YourStructOfError,
},
}
// pass the default responses to instance of your chosen framework
e := NewEcho(defaultResponses)
Then it will add default responses for all routes, like the example below:
// @Summary Logout
// @Description Logout the user
// @Tags auth
// @Param user-token header string true "User access token"
// @Success 200
// @Failure 400 {object} YourStructOfError
// @Failure 401 {object} YourStructOfError
// @Router /auth/logout [post]
func handleLogout() {} //nolint:unused
// @Summary Login
// @Description Login the user
// @Tags auth
// @Param user-token header string true "User access token"
// @Success 200
// @Failure 400 {object} YourStructOfError
// @Failure 401 {object} YourStructOfError
// @Router /auth/login [post]
func handleLogin() {} //nolint:unused
When you organize a monolith around bounded contexts (e.g. internal/provider/.../authroute and internal/nexus/.../authroute), it's natural to have handlers with identical short names — handleLogin, handleLogout, handlePing — in each context. Goswag automatically disambiguates these by appending a short, deterministic hash of the handler's package path to the stub function name in the generated goswag.go:
// @Router /provider/auth/login [post]
func handleLogin_a3f2c9d1() {} //nolint:unused
// @Router /nexus/auth/login [post]
func handleLogin_b71e04f8() {} //nolint:unused
The hash is only used as a unique Go identifier for the stub — it never leaks into the generated swagger.json/swagger.yaml, so the documentation stays clean. No action required on your side: just write handleLogin once per context like you normally would.
NewEcho() and NewGin() includes de defaultResponses parameter as optional, then you can pass your default responses only if you want =].
To see an example of usage, you can check this repository.
The necessary modifications are located in transport/rest/server.go and the router.go file inside of each route directory in transport/rest/routes/.
You can add description for fields, add if they are required or not.
For this struct fields features and more, you can follow the swag documentation to understand how to add it.
Contributions are welcomed. :)
You can contribute not only with code but also by enhancing these README.md docs, writing articles, using Goswag and providing feedback.
To contribute, please follow these steps:
git checkout -b feature/<FEATURE NAME>)git commit -m "Add some feature")git push origin feature/<FEATURE NAME>)Goswag is MIT licensed.
$ claude mcp add goswag \
-- python -m otcore.mcp_server <graph>