Annotations Reference

Introduction

Hiboot uses struct tags (annotations) to configure controllers, dependency injection, and Swagger documentation. This reference documents all available annotations in the at package.

Controller Annotations

at.RestController

Marks a struct as a REST controller:

type userController struct {
	at.RestController
}

at.RequestMapping

Defines the base URL path for all methods in the controller:

type userController struct {
	at.RestController
	at.RequestMapping `value:"/api/users"`
}

HTTP Method Annotations

at.GetMapping

Maps a method to HTTP GET:

func (c *userController) GetUser(
	at struct {
		at.GetMapping `value:"/{id}"`
	},
	id uint64,
) (model.Response, error) {
	// Handle GET /api/users/{id}
}

at.PostMapping

Maps a method to HTTP POST:

func (c *userController) CreateUser(
	at struct {
		at.PostMapping `value:"/"`
	},
	request *CreateUserRequest,
) (model.Response, error) {
	// Handle POST /api/users/
}

at.PutMapping

Maps a method to HTTP PUT:

func (c *userController) UpdateUser(
	at struct {
		at.PutMapping `value:"/{id}"`
	},
	id uint64,
	request *UpdateUserRequest,
) (model.Response, error) {
	// Handle PUT /api/users/{id}
}

at.DeleteMapping

Maps a method to HTTP DELETE:

func (c *userController) DeleteUser(
	at struct {
		at.DeleteMapping `value:"/{id}"`
	},
	id uint64,
) (model.Response, error) {
	// Handle DELETE /api/users/{id}
}

at.PatchMapping

Maps a method to HTTP PATCH:

func (c *userController) PatchUser(
	at struct {
		at.PatchMapping `value:"/{id}"`
	},
	id uint64,
	request *PatchUserRequest,
) (model.Response, error) {
	// Handle PATCH /api/users/{id}
}

Dependency Injection Annotations

inject

Injects a dependency by type or name:

type userController struct {
	at.RestController

	// Inject by type
	UserService *service.UserService `inject:""`

	// Inject by name
	PrimaryDB *gorm.DB `inject:"primaryDatabase"`
}

value

Injects a configuration value:

type Config struct {
	AppName  string `value:"${app.name}"`
	Port     int    `value:"${server.port}"`
	LogLevel string `value:"${logging.level:info}"` // with default
}

default

Sets a default value for a field:

type Config struct {
	Timeout int    `default:"30"`
	Host    string `default:"localhost"`
	Enabled bool   `default:"true"`
}

Swagger/OpenAPI Annotations

at.Operation

Describes an API operation:

func (c *userController) GetUser(
	at struct {
		at.GetMapping `value:"/{id}"`
		at.Operation  `id:"getUserById" description:"Get user by ID"`
	},
	id uint64,
) (model.Response, error) {
	// ...
}
Attribute Description
id Operation ID (unique)
description Operation description
summary Short summary
tags API tags for grouping

at.Produces

Specifies the response content types:

func (c *userController) GetUser(
	at struct {
		at.GetMapping `value:"/{id}"`
		at.Produces   `values:"application/json"`
	},
	id uint64,
) (model.Response, error) {
	// ...
}

at.Consumes

Specifies the request content types:

func (c *userController) CreateUser(
	at struct {
		at.PostMapping `value:"/"`
		at.Consumes    `values:"application/json"`
	},
	request *CreateUserRequest,
) (model.Response, error) {
	// ...
}

at.Parameter

Describes a parameter:

func (c *userController) GetUser(
	at struct {
		at.GetMapping `value:"/{id}"`
		Parameters    struct {
			Id struct {
				at.Parameter `name:"id" in:"path" type:"integer" description:"User ID" required:"true"`
			}
		}
	},
	id uint64,
) (model.Response, error) {
	// ...
}
Attribute Description
name Parameter name
in Location: path, query, header, body
type Data type
description Parameter description
required Whether required

at.Response

Describes an API response:

func (c *userController) GetUser(
	at struct {
		at.GetMapping `value:"/{id}"`
		Responses     struct {
			Success struct {
				at.Response `code:"200" description:"Success"`
			}
			NotFound struct {
				at.Response `code:"404" description:"User not found"`
			}
		}
	},
	id uint64,
) (model.Response, error) {
	// ...
}
Attribute Description
code HTTP status code
description Response description

at.Schema

Describes the response schema:

func (c *userController) GetUser(
	at struct {
		at.GetMapping `value:"/{id}"`
		Responses     struct {
			Success struct {
				at.Response `code:"200" description:"Success"`
				at.Schema   `type:"object" ref:"User"`
			}
		}
	},
	id uint64,
) (model.Response, error) {
	// ...
}

Configuration Annotations

mapstructure

Maps YAML configuration to struct fields:

type configuration struct {
	app.Configuration

	DatabaseProps Properties `mapstructure:"database"`
}

In application.yml:

database:
  host: localhost
  port: 5432

after

Specifies configuration loading order:

type configuration struct {
	app.Configuration `after:"databaseConfiguration"`
}

missing

Conditional configuration loading:

type configuration struct {
	app.Configuration `missing:"customConfiguration"`
}

CLI Command Annotations

cli.RootCommand

Marks a struct as the root CLI command:

type RootCommand struct {
	cli.RootCommand
}

cli.SubCommand

Marks a struct as a sub-command:

type userCommand struct {
	cli.SubCommand
}

Complete Example

package controller

import (
	"github.com/hidevopsio/hiboot/pkg/app"
	"github.com/hidevopsio/hiboot/pkg/at"
	"github.com/hidevopsio/hiboot/pkg/model"
)

type userController struct {
	at.RestController
	at.RequestMapping `value:"/api/users"`

	userService UserService `inject:""`
	appName     string      `value:"${app.name}"`
}

func init() {
	app.Register(newUserController)
}

func newUserController(userService UserService) *userController {
	return &userController{
		userService: userService,
	}
}

// GetById handles GET /api/users/{id}
func (c *userController) GetById(
	at struct {
		at.GetMapping `value:"/{id}"`
		at.Operation  `id:"getUserById" description:"Get user by ID"`
		at.Produces   `values:"application/json"`
		Parameters    struct {
			Id struct {
				at.Parameter `name:"id" in:"path" type:"integer" description:"User ID" required:"true"`
			}
		}
		Responses struct {
			Success struct {
				at.Response `code:"200" description:"User found"`
			}
			NotFound struct {
				at.Response `code:"404" description:"User not found"`
			}
		}
	},
	id uint64,
) (model.Response, error) {
	user, err := c.userService.GetUser(id)
	if err != nil {
		response := new(model.BaseResponse)
		response.SetCode(404)
		return response, nil
	}

	response := new(model.BaseResponse)
	response.SetData(user)
	return response, nil
}

What’s Next?