Documentation Index Fetch the complete documentation index at: https://mintlify.com/go-kratos/kratos/llms.txt
Use this file to discover all available pages before exploring further.
Kratos provides custom protoc plugins to generate HTTP bindings and error definitions from Protocol Buffer files.
Overview
Kratos code generation includes:
protoc-gen-go-http : Generates HTTP server and client code from protobuf with Google API annotations
protoc-gen-go-errors : Generates type-safe error definitions from enums
Standard protoc plugins for gRPC and protobuf messages
Installation
Install Protocol Buffer Compiler
# macOS
brew install protobuf
# Linux
apt install -y protobuf-compiler
# Verify installation
protoc --version
Install all required protoc plugins:
# Standard Go protobuf plugin
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# gRPC plugin
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# Kratos HTTP plugin
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest
# Kratos errors plugin
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2@latest
# OpenAPI plugin (optional)
go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest
Check that plugins are in your PATH:
which protoc-gen-go-http
which protoc-gen-go-errors
Using protoc-gen-go-http
The HTTP plugin generates server routing and client code from protobuf definitions.
Basic Usage
Generate HTTP bindings from a protobuf file:
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--go-http_out=paths=source_relative:. \
api/helloworld/v1/ * .proto
Generated Code Structure
For this protobuf definition:
api/helloworld/v1/greeter.proto
service Greeter {
rpc SayHello ( HelloRequest ) returns ( HelloReply ) {
option (google.api.http) = {
get : "/helloworld/{name}"
};
}
}
The plugin generates greeter_http.pb.go with:
// HTTP Server Registration
func RegisterGreeterHTTPServer ( s * http . Server , srv GreeterHTTPServer ) {
r := s . Route ( "/" )
r . GET ( "/helloworld/{name}" , _Greeter_SayHello0_HTTP_Handler ( srv ))
}
// HTTP Handler
func _Greeter_SayHello0_HTTP_Handler ( srv GreeterHTTPServer ) func ( ctx http . Context ) error {
return func ( ctx http . Context ) error {
var in HelloRequest
if err := ctx . BindVars ( & in ); err != nil {
return err
}
http . SetOperation ( ctx , "/helloworld.v1.Greeter/SayHello" )
h := ctx . Middleware ( func ( ctx context . Context , req interface {}) ( interface {}, error ) {
return srv . SayHello ( ctx , req .( * HelloRequest ))
})
out , err := h ( ctx , & in )
if err != nil {
return err
}
reply := out .( * HelloReply )
return ctx . Result ( 200 , reply )
}
}
HTTP Method Mapping
The plugin supports all HTTP methods:
service ProductService {
// GET request
rpc GetProduct ( GetProductRequest ) returns ( Product ) {
option (google.api.http) = {
get : "/v1/products/{id}"
};
}
// POST request
rpc CreateProduct ( CreateProductRequest ) returns ( Product ) {
option (google.api.http) = {
post : "/v1/products"
body : "*"
};
}
// PUT request
rpc UpdateProduct ( UpdateProductRequest ) returns ( Product ) {
option (google.api.http) = {
put : "/v1/products/{id}"
body : "*"
};
}
// PATCH request
rpc PatchProduct ( PatchProductRequest ) returns ( Product ) {
option (google.api.http) = {
patch : "/v1/products/{id}"
body : "*"
};
}
// DELETE request
rpc DeleteProduct ( DeleteProductRequest ) returns ( google . protobuf . Empty ) {
option (google.api.http) = {
delete : "/v1/products/{id}"
};
}
}
Path Variable Binding
The plugin automatically binds path variables to request fields:
rpc GetArticle (GetArticleRequest) returns (Article) {
option (google.api.http) = {
get : "/v1/authors/{author_id}/articles/{article_id}"
};
}
message GetArticleRequest {
string author_id = 1 ; // Bound from path
string article_id = 2 ; // Bound from path
}
Body Binding
Control how request bodies are bound:
// Entire request as body
rpc CreateUser (CreateUserRequest) returns (User) {
option (google.api.http) = {
post : "/v1/users"
body : "*" // All fields in body
};
}
// Specific field as body
rpc UpdateProfile (UpdateProfileRequest) returns (Profile) {
option (google.api.http) = {
put : "/v1/users/{user_id}/profile"
body : "profile" // Only profile field in body
};
}
message UpdateProfileRequest {
string user_id = 1 ; // From path
Profile profile = 2 ; // From body
}
Response Body Customization
Customize the response body:
rpc GetUserStats (GetUserStatsRequest) returns (GetUserStatsResponse) {
option (google.api.http) = {
get : "/v1/users/{user_id}/stats"
response_body : "stats" // Only return the stats field
};
}
message GetUserStatsResponse {
UserStats stats = 1 ;
Metadata metadata = 2 ; // Not included in response
}
Using protoc-gen-go-errors
The errors plugin generates type-safe error constructors from enum definitions.
Basic Usage
Generate error definitions:
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--go-errors_out=paths=source_relative:. \
api/helloworld/v1/errors.proto
Define Error Enums
Create an errors protobuf file:
api/helloworld/v1/errors.proto
syntax = "proto3" ;
package helloworld.v1 ;
option go_package = "helloworld/api/helloworld/v1;v1" ;
import "errors/errors.proto" ;
enum ErrorReason {
// Set default HTTP status code
option (errors.default_code) = 500 ;
// Define specific errors with HTTP codes
USER_NOT_FOUND = 0 [ (errors.code) = 404 ];
USER_ALREADY_EXISTS = 1 [ (errors.code) = 409 ];
INVALID_ARGUMENT = 2 [ (errors.code) = 400 ];
UNAUTHORIZED = 3 [ (errors.code) = 401 ];
PERMISSION_DENIED = 4 [ (errors.code) = 403 ];
INTERNAL_ERROR = 5 [ (errors.code) = 500 ];
}
Generated Error Code
The plugin generates helper functions:
api/helloworld/v1/errors.pb.go
// Check if error is of specific type
func IsUserNotFound ( err error ) bool {
if err == nil {
return false
}
e := errors . FromError ( err )
return e . Reason == ErrorReason_USER_NOT_FOUND . String () && e . Code == 404
}
// Create new error
func ErrorUserNotFound ( format string , args ... interface {}) * errors . Error {
return errors . New ( 404 , ErrorReason_USER_NOT_FOUND . String (), fmt . Sprintf ( format , args ... ))
}
// Other generated functions
func IsUserAlreadyExists ( err error ) bool
func ErrorUserAlreadyExists ( format string , args ... interface {}) * errors . Error
// ... etc
Using Generated Errors
Use the generated functions in your service:
func ( s * UserService ) GetUser ( ctx context . Context , req * v1 . GetUserRequest ) ( * v1 . User , error ) {
user , err := s . repo . FindUser ( ctx , req . Id )
if err != nil {
if errors . Is ( err , gorm . ErrRecordNotFound ) {
return nil , v1 . ErrorUserNotFound ( "user %s not found" , req . Id )
}
return nil , v1 . ErrorInternalError ( "failed to get user: %v " , err )
}
return user , nil
}
func ( s * UserService ) CreateUser ( ctx context . Context , req * v1 . CreateUserRequest ) ( * v1 . User , error ) {
exists , _ := s . repo . UserExists ( ctx , req . Email )
if exists {
return nil , v1 . ErrorUserAlreadyExists ( "user with email %s already exists" , req . Email )
}
// ... create user
}
Makefile Integration
Create a Makefile for easy code generation:
.PHONY : api
api :
@ echo "Generating API code..."
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--go-http_out=paths=source_relative:. \
--go-grpc_out=paths=source_relative:. \
--go-errors_out=paths=source_relative:. \
api/**/*.proto
@ echo "API code generated successfully"
.PHONY : openapi
openapi :
protoc --proto_path=. \
--proto_path=./third_party \
--openapi_out=fq_schema_naming=true,default_response=false:. \
api/**/*.proto
Run generation:
Configuration File
Use a configuration file for complex setups:
version : v1
plugins :
- name : go
out : .
opt :
- paths=source_relative
- name : go-grpc
out : .
opt :
- paths=source_relative
- name : go-http
out : .
opt :
- paths=source_relative
- name : go-errors
out : .
opt :
- paths=source_relative
Best Practices
Version Control Commit generated code to version control for reproducibility
CI/CD Integration Run code generation in CI to ensure it’s always up to date
Code Reviews Review generated code changes to catch API breaking changes
Documentation Generate OpenAPI specs for API documentation
Troubleshooting
Ensure third_party directory contains Google API protos: git clone https://github.com/googleapis/googleapis third_party/googleapis
Verify plugins are in PATH and executable: export PATH = $PATH :$( go env GOPATH )/ bin
Generated code has wrong imports
Check the go_package option in your proto files matches your module structure.
Next Steps
Service Implementation Implement your generated service interfaces
Testing Learn how to test generated code