1. Project Overview & Quickstart (zeromicro/go-zero)
File: README.md
go-zero
go-zero is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
🤷 What is go-zero?
go-zero (listed in CNCF Landscape: https://landscape.cncf.io/?selected=go-zero) is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
go-zero contains simple API description syntax and code generation tool called goctl. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with goctl.
Advantages of go-zero:
- Improves the stability of the services with tens of millions of daily active users
- Builtin chained timeout control, concurrency control, rate limit, adaptive circuit breaker, adaptive load shedding, even no configuration needed
- Builtin middlewares also can be integrated into your frameworks
- Simple API syntax, one command to generate a couple of different languages
- Auto validate the request parameters from clients
- Plenty of builtin microservice management and concurrent toolkits
Backgrounds of go-zero
In early 2018, we transitioned from a Java+MongoDB monolithic architecture to microservices, choosing:
- Golang - High performance, simple syntax, excellent deployment experience, and low resource consumption
- Self-designed microservice framework - Better problem isolation, easier feature extension, and faster issue resolution
Design considerations on go-zero
go-zero follows these core design principles:
- Simplicity - Keep it simple, first principle
- High availability - Stable under high concurrency
- Resilience - Failure-oriented programming with adaptive protection
- Developer friendly - Encapsulate complexity, one way to do one thing
- Easy to extend - Flexible architecture for growth
The implementation and features of go-zero
go-zero integrates engineering best practices:
- Code generation - Powerful tools to minimize boilerplate
- Simple API - Clean interfaces, fully compatible with net/http
- High performance - Optimized for speed and efficiency
- Resilience - Built-in circuit breaker, rate limiting, load shedding, timeout control
- Service mesh - Service discovery, load balancing, call tracing
- Developer tools - Auto parameter validation, cache management, metrics and monitoring
Architecture with go-zero
Installation
Run the following command under your project:
go get -u github.com/zeromicro/go-zeroAI-Native Development
The go-zero team provides AI tooling for Claude, GitHub Copilot, Cursor to generate framework-compliant code.
Three Core Projects
ai-context - Workflow guide for AI assistants
zero-skills - Pattern library with examples
mcp-zero - Code generation tools via Model Context Protocol
Quick Setup
GitHub Copilot
git submodule add https://github.com/zeromicro/ai-context.git .github/ai-context
ln -s ai-context/00-instructions.md .github/copilot-instructions.md # macOS/Linux
# Windows: mklink .github\copilot-instructions.md .github\ai-context\00-instructions.md
git submodule update --remote .github/ai-context # UpdateCursor
git submodule add https://github.com/zeromicro/ai-context.git .cursorrules
git submodule update --remote .cursorrules # UpdateWindsurf
git submodule add https://github.com/zeromicro/ai-context.git .windsurfrules
git submodule update --remote .windsurfrules # UpdateClaude Desktop
git clone https://github.com/zeromicro/mcp-zero.git && cd mcp-zero && go build
# Configure: ~/Library/Application Support/Claude/claude_desktop_config.json
# Or: claude mcp add --transport stdio mcp-zero --env GOCTL_PATH=/path/to/goctl -- /path/to/mcp-zeroHow It Works
AI assistants use these tools together:
- ai-context - workflow guidance
- zero-skills - implementation patterns
- mcp-zero - real-time code generation
Example: Creating a REST API → AI reads ai-context for workflow → calls mcp-zero to generate code → references zero-skills for patterns → produces production-ready code ✅
Quick Start
Full examples:
Install goctl
shell# for Go go install github.com/zeromicro/go-zero/tools/goctl@latest # For Mac brew install goctl # docker for all platforms docker pull kevinwan/goctl # run goctl docker run --rm -it -v `pwd`:/app kevinwan/goctl --helpEnsure goctl is executable and in your $PATH.
Create the API file (greet.api):
gotype ( Request { Name string `path:"name,options=[you,me]"` // parameters are auto validated } Response { Message string `json:"message"` } ) service greet-api { @handler GreetHandler get /greet/from/:name(Request) returns (Response) }Generate .api template:
shellgoctl api -o greet.apiGenerate Go server code
shellgoctl api go -api greet.api -dir greetGenerated structure:
plain text├── greet │ ├── etc │ │ └── greet-api.yaml // configuration file │ ├── greet.go // main file │ └── internal │ ├── config │ │ └── config.go // configuration definition │ ├── handler │ │ ├── greethandler.go // get/put/post/delete routes are defined here │ │ └── routes.go // routes list │ ├── logic │ │ └── greetlogic.go // request logic can be written here │ ├── svc │ │ └── servicecontext.go // service context, mysql/redis can be passed in here │ └── types │ └── types.go // request/response defined here └── greet.api // api description fileRun the service:
shellcd greet go mod tidy go run greet.go -f etc/greet-api.yamlDefault port: 8888 (configurable in etc/greet-api.yaml)
Test with curl:
shellcurl -i http://localhost:8888/greet/from/youResponse:
httpHTTP/1.1 200 OK Date: Sun, 30 Aug 2020 15:32:35 GMT Content-Length: 0Write business logic
- Pass dependencies (mysql, redis, etc.) via servicecontext.go
- Add logic code in the logic package per .api definition
Generate client code for multiple languages
shellgoctl api java -api greet.api -dir greet goctl api dart -api greet.api -dir greet ...
Benchmark
Documents
- Documents
- Rapid development of microservice systems
- Rapid development of microservice systems - multiple RPCs
- Examples
Chat group
Join the chat via https://discord.gg/4JQvC5A4Fe
Cloud Native Landscape
go-zero enlisted in the CNCF Cloud Native Landscape.
Give a Star! ⭐
If you like this project or are using it to learn or start your own solution, give it a star to get updates on new releases. Your support matters!
File: Readme.md
go-zero
go-zero is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
🤷 What is go-zero?
go-zero (listed in CNCF Landscape: https://landscape.cncf.io/?selected=go-zero) is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
go-zero contains simple API description syntax and code generation tool called goctl. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with goctl.
Advantages of go-zero:
- Improves the stability of the services with tens of millions of daily active users
- Builtin chained timeout control, concurrency control, rate limit, adaptive circuit breaker, adaptive load shedding, even no configuration needed
- Builtin middlewares also can be integrated into your frameworks
- Simple API syntax, one command to generate a couple of different languages
- Auto validate the request parameters from clients
- Plenty of builtin microservice management and concurrent toolkits
Backgrounds of go-zero
In early 2018, we transitioned from a Java+MongoDB monolithic architecture to microservices, choosing:
- Golang - High performance, simple syntax, excellent deployment experience, and low resource consumption
- Self-designed microservice framework - Better problem isolation, easier feature extension, and faster issue resolution
Design considerations on go-zero
go-zero follows these core design principles:
- Simplicity - Keep it simple, first principle
- High availability - Stable under high concurrency
- Resilience - Failure-oriented programming with adaptive protection
- Developer friendly - Encapsulate complexity, one way to do one thing
- Easy to extend - Flexible architecture for growth
The implementation and features of go-zero
go-zero integrates engineering best practices:
- Code generation - Powerful tools to minimize boilerplate
- Simple API - Clean interfaces, fully compatible with net/http
- High performance - Optimized for speed and efficiency
- Resilience - Built-in circuit breaker, rate limiting, load shedding, timeout control
- Service mesh - Service discovery, load balancing, call tracing
- Developer tools - Auto parameter validation, cache management, metrics and monitoring
Architecture with go-zero
Installation
Run the following command under your project:
go get -u github.com/zeromicro/go-zeroAI-Native Development
The go-zero team provides AI tooling for Claude, GitHub Copilot, Cursor to generate framework-compliant code.
Three Core Projects
ai-context - Workflow guide for AI assistants
zero-skills - Pattern library with examples
mcp-zero - Code generation tools via Model Context Protocol
Quick Setup
GitHub Copilot
git submodule add https://github.com/zeromicro/ai-context.git .github/ai-context
ln -s ai-context/00-instructions.md .github/copilot-instructions.md # macOS/Linux
# Windows: mklink .github\copilot-instructions.md .github\ai-context\00-instructions.md
git submodule update --remote .github/ai-context # UpdateCursor
git submodule add https://github.com/zeromicro/ai-context.git .cursorrules
git submodule update --remote .cursorrules # UpdateWindsurf
git submodule add https://github.com/zeromicro/ai-context.git .windsurfrules
git submodule update --remote .windsurfrules # UpdateClaude Desktop
git clone https://github.com/zeromicro/mcp-zero.git && cd mcp-zero && go build
# Configure: ~/Library/Application Support/Claude/claude_desktop_config.json
# Or: claude mcp add --transport stdio mcp-zero --env GOCTL_PATH=/path/to/goctl -- /path/to/mcp-zeroHow It Works
AI assistants use these tools together:
- ai-context - workflow guidance
- zero-skills - implementation patterns
- mcp-zero - real-time code generation
Example: Creating a REST API → AI reads ai-context for workflow → calls mcp-zero to generate code → references zero-skills for patterns → produces production-ready code ✅
Quick Start
Full examples:
Install goctl
shell# for Go go install github.com/zeromicro/go-zero/tools/goctl@latest # For Mac brew install goctl # docker for all platforms docker pull kevinwan/goctl # run goctl docker run --rm -it -v `pwd`:/app kevinwan/goctl --helpEnsure goctl is executable and in your $PATH.
Create the API file (greet.api):
gotype ( Request { Name string `path:"name,options=[you,me]"` // parameters are auto validated } Response { Message string `json:"message"` } ) service greet-api { @handler GreetHandler get /greet/from/:name(Request) returns (Response) }Generate .api template:
shellgoctl api -o greet.apiGenerate Go server code
shellgoctl api go -api greet.api -dir greetGenerated structure:
plain text├── greet │ ├── etc │ │ └── greet-api.yaml // configuration file │ ├── greet.go // main file │ └── internal │ ├── config │ │ └── config.go // configuration definition │ ├── handler │ │ ├── greethandler.go // get/put/post/delete routes are defined here │ │ └── routes.go // routes list │ ├── logic │ │ └── greetlogic.go // request logic can be written here │ ├── svc │ │ └── servicecontext.go // service context, mysql/redis can be passed in here │ └── types │ └── types.go // request/response defined here └── greet.api // api description fileRun the service:
shellcd greet go mod tidy go run greet.go -f etc/greet-api.yamlDefault port: 8888 (configurable in etc/greet-api.yaml)
Test with curl:
shellcurl -i http://localhost:8888/greet/from/youResponse:
httpHTTP/1.1 200 OK Date: Sun, 30 Aug 2020 15:32:35 GMT Content-Length: 0Write business logic
- Pass dependencies (mysql, redis, etc.) via servicecontext.go
- Add logic code in the logic package per .api definition
Generate client code for multiple languages
shellgoctl api java -api greet.api -dir greet goctl api dart -api greet.api -dir greet ...
Benchmark
Documents
- Documents
- Rapid development of microservice systems
- Rapid development of microservice systems - multiple RPCs
- Examples
Chat group
Join the chat via https://discord.gg/4JQvC5A4Fe
Cloud Native Landscape
go-zero enlisted in the CNCF Cloud Native Landscape.
Give a Star! ⭐
If you like this project or are using it to learn or start your own solution, give it a star to get updates on new releases. Your support matters!
File: readme.md
go-zero
go-zero is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
🤷 What is go-zero?
go-zero (listed in CNCF Landscape: https://landscape.cncf.io/?selected=go-zero) is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
go-zero contains simple API description syntax and code generation tool called goctl. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with goctl.
Advantages of go-zero:
- Improves the stability of the services with tens of millions of daily active users
- Builtin chained timeout control, concurrency control, rate limit, adaptive circuit breaker, adaptive load shedding, even no configuration needed
- Builtin middlewares also can be integrated into your frameworks
- Simple API syntax, one command to generate a couple of different languages
- Auto validate the request parameters from clients
- Plenty of builtin microservice management and concurrent toolkits
Backgrounds of go-zero
In early 2018, we transitioned from a Java+MongoDB monolithic architecture to microservices, choosing:
- Golang - High performance, simple syntax, excellent deployment experience, and low resource consumption
- Self-designed microservice framework - Better problem isolation, easier feature extension, and faster issue resolution
Design considerations on go-zero
go-zero follows these core design principles:
- Simplicity - Keep it simple, first principle
- High availability - Stable under high concurrency
- Resilience - Failure-oriented programming with adaptive protection
- Developer friendly - Encapsulate complexity, one way to do one thing
- Easy to extend - Flexible architecture for growth
The implementation and features of go-zero
go-zero integrates engineering best practices:
- Code generation - Powerful tools to minimize boilerplate
- Simple API - Clean interfaces, fully compatible with net/http
- High performance - Optimized for speed and efficiency
- Resilience - Built-in circuit breaker, rate limiting, load shedding, timeout control
- Service mesh - Service discovery, load balancing, call tracing
- Developer tools - Auto parameter validation, cache management, metrics and monitoring
Architecture with go-zero
Installation
Run the following command under your project:
go get -u github.com/zeromicro/go-zeroAI-Native Development
The go-zero team provides AI tooling for Claude, GitHub Copilot, Cursor to generate framework-compliant code.
Three Core Projects
ai-context - Workflow guide for AI assistants
zero-skills - Pattern library with examples
mcp-zero - Code generation tools via Model Context Protocol
Quick Setup
GitHub Copilot
git submodule add https://github.com/zeromicro/ai-context.git .github/ai-context
ln -s ai-context/00-instructions.md .github/copilot-instructions.md # macOS/Linux
# Windows: mklink .github\copilot-instructions.md .github\ai-context\00-instructions.md
git submodule update --remote .github/ai-context # UpdateCursor
git submodule add https://github.com/zeromicro/ai-context.git .cursorrules
git submodule update --remote .cursorrules # UpdateWindsurf
git submodule add https://github.com/zeromicro/ai-context.git .windsurfrules
git submodule update --remote .windsurfrules # UpdateClaude Desktop
git clone https://github.com/zeromicro/mcp-zero.git && cd mcp-zero && go build
# Configure: ~/Library/Application Support/Claude/claude_desktop_config.json
# Or: claude mcp add --transport stdio mcp-zero --env GOCTL_PATH=/path/to/goctl -- /path/to/mcp-zeroHow It Works
AI assistants use these tools together:
- ai-context - workflow guidance
- zero-skills - implementation patterns
- mcp-zero - real-time code generation
Example: Creating a REST API → AI reads ai-context for workflow → calls mcp-zero to generate code → references zero-skills for patterns → produces production-ready code ✅
Quick Start
Full examples:
Install goctl
shell# for Go go install github.com/zeromicro/go-zero/tools/goctl@latest # For Mac brew install goctl # docker for all platforms docker pull kevinwan/goctl # run goctl docker run --rm -it -v `pwd`:/app kevinwan/goctl --helpEnsure goctl is executable and in your $PATH.
Create the API file (greet.api):
gotype ( Request { Name string `path:"name,options=[you,me]"` // parameters are auto validated } Response { Message string `json:"message"` } ) service greet-api { @handler GreetHandler get /greet/from/:name(Request) returns (Response) }Generate .api template:
shellgoctl api -o greet.apiGenerate Go server code
shellgoctl api go -api greet.api -dir greetGenerated structure:
plain text├── greet │ ├── etc │ │ └── greet-api.yaml // configuration file │ ├── greet.go // main file │ └── internal │ ├── config │ │ └── config.go // configuration definition │ ├── handler │ │ ├── greethandler.go // get/put/post/delete routes are defined here │ │ └── routes.go // routes list │ ├── logic │ │ └── greetlogic.go // request logic can be written here │ ├── svc │ │ └── servicecontext.go // service context, mysql/redis can be passed in here │ └── types │ └── types.go // request/response defined here └── greet.api // api description fileRun the service:
shellcd greet go mod tidy go run greet.go -f etc/greet-api.yamlDefault port: 8888 (configurable in etc/greet-api.yaml)
Test with curl:
shellcurl -i http://localhost:8888/greet/from/youResponse:
httpHTTP/1.1 200 OK Date: Sun, 30 Aug 2020 15:32:35 GMT Content-Length: 0Write business logic
- Pass dependencies (mysql, redis, etc.) via servicecontext.go
- Add logic code in the logic package per .api definition
Generate client code for multiple languages
shellgoctl api java -api greet.api -dir greet goctl api dart -api greet.api -dir greet ...
Benchmark
Documents
- Documents
- Rapid development of microservice systems
- Rapid development of microservice systems - multiple RPCs
- Examples
Chat group
Join the chat via https://discord.gg/4JQvC5A4Fe
Cloud Native Landscape
go-zero enlisted in the CNCF Cloud Native Landscape.
Give a Star! ⭐
If you like this project or are using it to learn or start your own solution, give it a star to get updates on new releases. Your support matters!
File: core/mr/readme.md
mapreduce
Why MapReduce is needed
In practical business scenarios we often need to get the corresponding properties from different RPC services to assemble complex objects.
For example, to query product details.
- product service - query product attributes
- inventory service - query inventory properties
- price service - query price attributes
- marketing service - query marketing properties
If it is a serial call, the response time will increase linearly with the number of RPC calls, so we will generally change serial to parallel to optimize response time.
Simple scenarios using WaitGroup can also meet the needs, but what if we need to check the data returned by the RPC call, data processing, data aggregation? The official go library does not have such a tool (CompletableFuture is provided in java), so we implemented an in-process data batching MapReduce concurrent tool based on the MapReduce architecture.
Design ideas
Let's try to put ourselves in the author's shoes and sort out the possible business scenarios for the concurrency tool:
- querying product details: supporting concurrent calls to multiple services to combine product attributes, and supporting call errors that can be ended immediately.
- automatic recommendation of user card coupons on product details page: support concurrently verifying card coupons, automatically rejecting them if they fail, and returning all of them.
The above is actually processing the input data and finally outputting the cleaned data. There is a very classic asynchronous pattern for data processing: the producer-consumer pattern. So we can abstract the life cycle of data batch processing, which can be roughly divided into three phases.
- data production generate
- data processing mapper
- data aggregation reducer
Data producing is an indispensable stage, data processing and data aggregation are optional stages, data producing and processing support concurrent calls, data aggregation is basically a pure memory operation, so a single concurrent process can do it.
Since different stages of data processing are performed by different goroutines, it is natural to consider the use of channel to achieve communication between goroutines.
How can I terminate the process at any time?
It's simple, just receive from a channel or the given context in the goroutine.
A simple example
Calculate the sum of squares, simulating the concurrency.
package main
import (
"fmt"
"log"
"github.com/zeromicro/go-zero/core/mr"
)
func main() {
val, err := mr.MapReduce(func(source chan<- int) {
// generator
for i := 0; i < 10; i++ {
source <- i
}
}, func(i int, writer mr.Writer[int], cancel func(error)) {
// mapper
writer.Write(i * i)
}, func(pipe <-chan int, writer mr.Writer[int], cancel func(error)) {
// reducer
var sum int
for i := range pipe {
sum += i
}
writer.Write(sum)
})
if err != nil {
log.Fatal(err)
}
fmt.Println("result:", val)
}More examples: https://github.com/zeromicro/zero-examples/tree/main/mapreduce
Give a Star! ⭐
If you like or are using this project to learn or start your solution, please give it a star. Thanks!
File: core/mr/readme-cn.md
mapreduce
为什么需要 MapReduce
在实际的业务场景中我们常常需要从不同的 RPC 服务中获取相应属性来组装成复杂对象。
比如要查询商品详情:
- 商品服务-查询商品属性
- 库存服务-查询库存属性
- 价格服务-查询价格属性
- 营销服务-查询营销属性
如果是串行调用的话响应时间会随着 RPC 调用次数呈线性增长,所以我们要优化性能一般会将串行改并行。
简单的场景下使用 WaitGroup 也能够满足需求,但是如果我们需要对 RPC 调用返回的数据进行校验、数据加工转换、数据汇总呢?继续使用 WaitGroup 就有点力不从心了,go 的官方库中并没有这种工具(java 中提供了 CompletableFuture),我们依据 MapReduce 架构思想实现了进程内的数据批处理 MapReduce 并发工具类。
设计思路
我们尝试把自己代入到作者的角色梳理一下并发工具可能的业务场景:
- 查询商品详情:支持并发调用多个服务来组合产品属性,支持调用错误可以立即结束。
- 商品详情页自动推荐用户卡券:支持并发校验卡券,校验失败自动剔除,返回全部卡券。
以上实际都是在进行对输入数据进行处理最后输出清洗后的数据,针对数据处理有个非常经典的异步模式:生产者消费者模式。于是我们可以抽象一下数据批处理的生命周期,大致可以分为三个阶段:
- 数据生产 generate
- 数据加工 mapper
- 数据聚合 reducer
其中数据生产是不可或缺的阶段,数据加工、数据聚合是可选阶段,数据生产与加工支持并发调用,数据聚合基本属于纯内存操作单协程即可。
再来思考一下不同阶段之间数据应该如何流转,既然不同阶段的数据处理都是由不同 goroutine 执行的,那么很自然的可以考虑采用 channel 来实现 goroutine 之间的通信。
如何实现随时终止流程呢?
goroutine 中监听一个全局的结束 channel 和调用方提供的 ctx 就行。
简单示例
并行求平方和(不要嫌弃示例简单,只是模拟并发)
package main
import (
"fmt"
"log"
"github.com/zeromicro/go-zero/core/mr"
)
func main() {
val, err := mr.MapReduce(func(source chan<- int) {
// generator
for i := 0; i < 10; i++ {
source <- i
}
}, func(i int, writer mr.Writer[int], cancel func(error)) {
// mapper
writer.Write(i * i)
}, func(pipe <-chan int, writer mr.Writer[int], cancel func(error)) {
// reducer
var sum int
for i := range pipe {
sum += i
}
writer.Write(sum)
})
if err != nil {
log.Fatal(err)
}
fmt.Println("result:", val)
}更多示例:https://github.com/zeromicro/zero-examples/tree/main/mapreduce
欢迎 star!⭐
如果你正在使用或者觉得这个项目对你有帮助,请 star 支持,感谢!
File: core/logx/readme.md
logx
logx configurations
type LogConf struct {
ServiceName string `json:",optional"`
Mode string `json:",default=console,options=[console,file,volume]"`
Encoding string `json:",default=json,options=[json,plain]"`
TimeFormat string `json:",optional"`
Path string `json:",default=logs"`
Level string `json:",default=info,options=[info,error,severe]"`
Compress bool `json:",optional"`
KeepDays int `json:",optional"`
StackCooldownMillis int `json:",default=100"`
MaxBackups int `json:",default=0"`
MaxSize int `json:",default=0"`
Rotation string `json:",default=daily,options=[daily,size]"`
}ServiceName: set the service name, optional. onvolumemode, the name is used to generate the log files. Withinrest/zrpcservices, the name will be set to the name ofrestorzrpcautomatically.Mode: the mode to output the logs, default isconsole.consolemode writes the logs tostdout/stderr.filemode writes the logs to the files specified byPath.volumemode is used in docker, to write logs into mounted volumes.
Encoding: indicates how to encode the logs, default isjson.jsonmode writes the logs in json format.plainmode writes the logs with plain text, with terminal color enabled.
TimeFormat: customize the time format, optional. Default is2006-01-02T15:04:05.000Z07:00.Path: set the log path, default tologs.Level: the logging level to filter logs. Default isinfo.info, all logs are written.error,infologs are suppressed.severe,infoanderrorlogs are suppressed, onlyseverelogs are written.
Compress: whether or not to compress log files, only works withfilemode.KeepDays: how many days that the log files are kept, after the given days, the outdated files will be deleted automatically. It has no effect onconsolemode.StackCooldownMillis: how many milliseconds to rewrite stacktrace again. It’s used to avoid stacktrace flooding.MaxBackups: represents how many backup log files will be kept. 0 means all files will be kept forever. Only take effect whenRotationissize. NOTE: the level of optionKeepDayswill be higher. Even thoughMaxBackupssets 0, log files will still be removed if theKeepDayslimitation is reached.MaxSize: represents how much space the writing log file takes up. 0 means no limit. The unit isMB. Only take effect whenRotationissize.Rotation: represents the type of log rotation rule. Default isdaily.dailyrotate the logs by day.sizerotate the logs by size of logs.
Logging methods
type Logger interface {
// Error logs a message at error level.
Error(...any)
// Errorf logs a message at error level.
Errorf(string, ...any)
// Errorv logs a message at error level.
Errorv(any)
// Errorw logs a message at error level.
Errorw(string, ...LogField)
// Info logs a message at info level.
Info(...any)
// Infof logs a message at info level.
Infof(string, ...any)
// Infov logs a message at info level.
Infov(any)
// Infow logs a message at info level.
Infow(string, ...LogField)
// Slow logs a message at slow level.
Slow(...any)
// Slowf logs a message at slow level.
Slowf(string, ...any)
// Slowv logs a message at slow level.
Slowv(any)
// Sloww logs a message at slow level.
Sloww(string, ...LogField)
// WithContext returns a new logger with the given context.
WithContext(context.Context) Logger
// WithDuration returns a new logger with the given duration.
WithDuration(time.Duration) Logger
}Error,Info,Slow: write any kind of messages into logs, with likefmt.Sprint(…).Errorf,Infof,Slowf: write messages with given format into logs.Errorv,Infov,Slowv: write any kind of messages into logs, with json marshalling to encode them.Errorw,Infow,Sloww: write the string message with givenkey:valuefields.WithContext: inject the given ctx into the log messages, typically used to logtrace-idandspan-id.WithDuration: write elapsed duration into the log messages, with keyduration.
Integrating with third-party logging libs
- zap
- logrus
For more libs, please implement and PR to https://github.com/zeromicro/zero-contrib
Write the logs to specific stores
logx defined two interfaces to let you customize logx to write logs into any stores.
logx.NewWriter(w io.Writer)logx.SetWriter(writer logx.Writer)
For example, if we want to write the logs into kafka instead of console or files, we can do it like below:
type KafkaWriter struct {
Pusher *kq.Pusher
}
func NewKafkaWriter(pusher *kq.Pusher) *KafkaWriter {
return &KafkaWriter{
Pusher: pusher,
}
}
func (w *KafkaWriter) Write(p []byte) (n int, err error) {
// writing log with newlines, trim them.
if err := w.Pusher.Push(strings.TrimSpace(string(p))); err != nil {
return 0, err
}
return len(p), nil
}
func main() {
pusher := kq.NewPusher([]string{"localhost:9092"}, "go-zero")
defer pusher.Close()
writer := logx.NewWriter(NewKafkaWriter(pusher))
logx.SetWriter(writer)
// more code
}Complete code: https://github.com/zeromicro/zero-examples/blob/main/logx/tokafka/main.go
Filtering sensitive fields
If we need to prevent the password fields from logging, we can do it like below:
type (
Message struct {
Name string
Password string
Message string
}
SensitiveLogger struct {
logx.Writer
}
)
func NewSensitiveLogger(writer logx.Writer) *SensitiveLogger {
return &SensitiveLogger{
Writer: writer,
}
}
func (l *SensitiveLogger) Info(msg any, fields ...logx.LogField) {
if m, ok := msg.(Message); ok {
l.Writer.Info(Message{
Name: m.Name,
Password: "******",
Message: m.Message,
}, fields...)
} else {
l.Writer.Info(msg, fields...)
}
}
func main() {
// setup logx to make sure originalWriter not nil,
// the injected writer is only for filtering, like a middleware.
originalWriter := logx.Reset()
writer := NewSensitiveLogger(originalWriter)
logx.SetWriter(writer)
logx.Infov(Message{
Name: "foo",
Password: "shouldNotAppear",
Message: "bar",
})
// more code
}Complete code: https://github.com/zeromicro/zero-examples/blob/main/logx/filterfields/main.go
More examples
https://github.com/zeromicro/zero-examples/tree/main/logx
Give a Star! ⭐
If you like or are using this project to learn or start your solution, please give it a star. Thanks!
File: core/logx/readme-cn.md
logx
logx 配置
type LogConf struct {
ServiceName string `json:",optional"`
Mode string `json:",default=console,options=[console,file,volume]"`
Encoding string `json:",default=json,options=[json,plain]"`
TimeFormat string `json:",optional"`
Path string `json:",default=logs"`
Level string `json:",default=info,options=[info,error,severe]"`
Compress bool `json:",optional"`
KeepDays int `json:",optional"`
StackCooldownMillis int `json:",default=100"`
MaxBackups int `json:",default=0"`
MaxSize int `json:",default=0"`
Rotation string `json:",default=daily,options=[daily,size]"`
}ServiceName:设置服务名称,可选。在volume模式下,该名称用于生成日志文件。在rest/zrpc服务中,名称将被自动设置为rest或zrpc的名称。Mode:输出日志的模式,默认是consoleconsole模式将日志写到stdout/stderrfile模式将日志写到Path指定目录的文件中volume模式在 docker 中使用,将日志写入挂载的卷中
Encoding: 指示如何对日志进行编码,默认是jsonjson模式以 json 格式写日志plain模式用纯文本写日志,并带有终端颜色显示
TimeFormat:自定义时间格式,可选。默认是2006-01-02T15:04:05.000Z07:00Path:设置日志路径,默认为logsLevel: 用于过滤日志的日志级别。默认为infoinfo,所有日志都被写入error,info的日志被丢弃severe,info和error日志被丢弃,只有severe日志被写入
Compress: 是否压缩日志文件,只在file模式下工作KeepDays:日志文件被保留多少天,在给定的天数之后,过期的文件将被自动删除。对console模式没有影响StackCooldownMillis:多少毫秒后再次写入堆栈跟踪。用来避免堆栈跟踪日志过多MaxBackups: 多少个日志文件备份将被保存。0代表所有备份都被保存。当Rotation被设置为size时才会起作用。注意:KeepDays选项的优先级会比MaxBackups高,即使MaxBackups被设置为0,当达到KeepDays上限时备份文件同样会被删除。MaxSize: 当前被写入的日志文件最大可占用多少空间。0代表没有上限。单位为MB。当Rotation被设置为size时才会起作用。Rotation: 日志轮转策略类型。默认为daily(按天轮转)。daily按天轮转。size按日志大小轮转。
打印日志方法
type Logger interface {
// Error logs a message at error level.
Error(...any)
// Errorf logs a message at error level.
Errorf(string, ...any)
// Errorv logs a message at error level.
Errorv(any)
// Errorw logs a message at error level.
Errorw(string, ...LogField)
// Info logs a message at info level.
Info(...any)
// Infof logs a message at info level.
Infof(string, ...any)
// Infov logs a message at info level.
Infov(any)
// Infow logs a message at info level.
Infow(string, ...LogField)
// Slow logs a message at slow level.
Slow(...any)
// Slowf logs a message at slow level.
Slowf(string, ...any)
// Slowv logs a message at slow level.
Slowv(any)
// Sloww logs a message at slow level.
Sloww(string, ...LogField)
// WithContext returns a new logger with the given context.
WithContext(context.Context) Logger
// WithDuration returns a new logger with the given duration.
WithDuration(time.Duration) Logger
}Error,Info,Slow: 将任何类型的信息写进日志,使用fmt.Sprint(...)来转换为stringErrorf,Infof,Slowf: 将指定格式的信息写入日志Errorv,Infov,Slowv: 将任何类型的信息写入日志,用json marshal编码Errorw,Infow,Sloww: 写日志,并带上给定的key:value字段WithContext:将给定的 ctx 注入日志信息,例如用于记录trace-id和span-idWithDuration: 将指定的时间写入日志信息中,字段名为duration
与第三方日志库集成
- zap
- logrus
对于其它的日志库,请参考上面示例实现,并欢迎提交 PR 到 https://github.com/zeromicro/zero-contrib
将日志写到指定的存储
logx定义了两个接口,方便自定义 logx,将日志写入任何存储。
logx.NewWriter(w io.Writer)logx.SetWriter(write logx.Writer)
例如,如果我们想把日志写进kafka,而不是控制台或文件,我们可以像下面这样做。
type KafkaWriter struct {
Pusher *kq.Pusher
}
func NewKafkaWriter(pusher *kq.Pusher) *KafkaWriter {
return &KafkaWriter{
Pusher: pusher,
}
}
func (w *KafkaWriter) Write(p []byte) (n int, err error) {
// writing log with newlines, trim them.
if err := w.Pusher.Push(strings.TrimSpace(string(p))); err != nil {
return 0, err
}
return len(p), nil
}
func main() {
pusher := kq.NewPusher([]string{"localhost:9092"}, "go-zero")
defer pusher.Close()
writer := logx.NewWriter(NewKafkaWriter(pusher))
logx.SetWriter(writer)
// more code
}完整代码:https://github.com/zeromicro/zero-examples/blob/main/logx/tokafka/main.go
过滤敏感字段
如果我们需要防止 password 字段被记录下来,我们可以像下面这样实现。
type (
Message struct {
Name string
Password string
Message string
}
SensitiveLogger struct {
logx.Writer
}
)
func NewSensitiveLogger(writer logx.Writer) *SensitiveLogger {
return &SensitiveLogger{
Writer: writer,
}
}
func (l *SensitiveLogger) Info(msg any, fields ...logx.LogField) {
if m, ok := msg.(Message); ok {
l.Writer.Info(Message{
Name: m.Name,
Password: "******",
Message: m.Message,
}, fields...)
} else {
l.Writer.Info(msg, fields...)
}
}
func main() {
// setup logx to make sure originalWriter not nil,
// the injected writer is only for filtering, like a middleware.
originalWriter := logx.Reset()
writer := NewSensitiveLogger(originalWriter)
logx.SetWriter(writer)
logx.Infov(Message{
Name: "foo",
Password: "shouldNotAppear",
Message: "bar",
})
// more code
}完整代码:https://github.com/zeromicro/zero-examples/blob/main/logx/filterfields/main.go
更多示例
https://github.com/zeromicro/zero-examples/tree/main/logx
Give a Star! ⭐
如果你正在使用或者觉得这个项目对你有帮助,请 star 支持,感谢!
File: core/conf/readme.md
How to use
- Define a config structure, like below:
type RestfulConf struct {
ServiceName string `json:",env=SERVICE_NAME"` // read from env automatically
Host string `json:",default=0.0.0.0"`
Port int
LogMode string `json:",options=[file,console]"`
Verbose bool `json:",optional"`
MaxConns int `json:",default=10000"`
MaxBytes int64 `json:",default=1048576"`
Timeout time.Duration `json:",default=3s"`
CpuThreshold int64 `json:",default=900,range=[0:1000)"`
}- Write the yaml, toml or json config file:
- yaml example
# most fields are optional or have default values
port: 8080
logMode: console
# you can use env settings
maxBytes: ${MAX_BYTES}- toml example
# most fields are optional or have default values
port = 8_080
logMode = "console"
# you can use env settings
maxBytes = "${MAX_BYTES}"- Load the config from a file:
// exit on error
var config RestfulConf
conf.MustLoad(configFile, &config)
// or handle the error on your own
var config RestfulConf
if err := conf.Load(configFile, &config); err != nil {
log.Fatal(err)
}
// enable reading from environments
var config RestfulConf
conf.MustLoad(configFile, &config, conf.UseEnv())File: gateway/readme.md
Gateway
Usage
- main.go
var configFile = flag.String("f", "config.yaml", "config file")
func main() {
flag.Parse()
var c gateway.GatewayConf
conf.MustLoad(*configFile, &c)
gw := gateway.MustNewServer(c)
defer gw.Stop()
gw.Start()
}- config.yaml
Name: demo-gateway
Host: localhost
Port: 8888
Upstreams:
- Grpc:
Etcd:
Hosts:
- localhost:2379
Key: hello.rpc
# protoset mode
ProtoSets:
- hello.pb
# Mappings can also be written in proto options
Mappings:
- Method: get
Path: /pingHello/:ping
RpcPath: hello.Hello/Ping
- Grpc:
Endpoints:
- localhost:8081
# reflection mode, no ProtoSet settings
Mappings:
- Method: post
Path: /pingWorld
RpcPath: world.World/PingGenerate ProtoSet files
- example command without external imports
protoc --descriptor_set_out=hello.pb hello.proto- example command with external imports
protoc --include_imports --proto_path=. --descriptor_set_out=hello.pb hello.protoFile: mcp/readme.md
Model Context Protocol (MCP) Implementation
Overview
This package provides a go-zero integration for the Model Context Protocol (MCP) using the official go-sdk. It wraps the official MCP SDK to provide a seamless integration with go-zero's REST server framework.
Features
- Official SDK Integration: Built on top of the official Model Context Protocol Go SDK
- No SDK Import Required: Use
mcp.AddTool()directly without importing the official SDK - go-zero Integration: Seamlessly integrates with go-zero's REST server and configuration system
- Dual Transport Support:
- SSE (Server-Sent Events) transport for 2024-11-05 MCP spec
- Streamable HTTP transport for 2025-03-26 MCP spec
- CORS Support: Configurable CORS settings for cross-origin requests
- Type-Safe Tool Handlers: Generic tool handlers with automatic JSON schema generation
- Prompts and Resources: Full support for MCP prompts and resources
- Request Metadata Bridge: Optional request metadata extraction into handler context
Quick Start
1. Installation
go get github.com/zeromicro/go-zeroNote: The official MCP SDK is a transitive dependency and will be installed automatically. You don't need to import it directly in your code.
2. Configuration
Create a configuration file config.yaml:
name: my-mcp-server
host: localhost
port: 8080
mcp:
name: my-mcp-server
version: 1.0.0
useStreamable: false # Use SSE transport (default), set to true for Streamable HTTP
sseEndpoint: /sse
messageEndpoint: /message
sseTimeout: 24h
messageTimeout: 30s
cors:
- http://localhost:30003. Create Your Server
package main
import (
"context"
"log"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/mcp"
)
type GreetArgs struct {
Name string `json:"name" jsonschema:"description=Name of the person to greet"`
}
func main() {
// Load configuration
var c mcp.McpConf
conf.MustLoad("config.yaml", &c)
// Create MCP server
server := mcp.NewMcpServer(c)
// Register a tool with automatic schema generation using the SDK directly
tool := &mcp.Tool{
Name: "greet",
}
handler := func(ctx context.Context, req *mcp.CallToolRequest, args GreetArgs) (*mcp.CallToolResult, any, error) {
return &mcp.CallToolResult{
Content: []mcp.Content{
&mcp.TextContent{Text: "Hello, " + args.Name + "!"},
},
}, nil, nil
}
// Register tool with type-safe generics - no need to import official SDK
mcp.AddTool(server, tool, handler)
// Start server
defer server.Stop()
server.Start()
}Adding Tools
Tools are functions that the MCP client can call. The SDK automatically generates JSON schemas from your struct tags. Use sdkmcp.AddTool with the server's underlying SDK server:
type CalculateArgs struct {
Operation string `json:"operation" jsonschema:"enum=add,enum=subtract,enum=multiply,enum=divide"`
A float64 `json:"a" jsonschema:"description=First number"`
B float64 `json:"b" jsonschema:"description=Second number"`
}
tool := &mcp.Tool{
Name: "calculate",
}
handler := func(ctx context.Context, req *mcp.CallToolRequest, args CalculateArgs) (*mcp.CallToolResult, any, error) {
var result float64
switch args.Operation {
case "add":
result = args.A + args.B
case "subtract":
result = args.A - args.B
case "multiply":
result = args.A * args.B
case "divide":
if args.B == 0 {
return &mcp.CallToolResult{IsError: true}, nil, fmt.Errorf("division by zero")
}
result = args.A / args.B
}
return &mcp.CallToolResult{
Content: []mcp.Content{
&mcp.TextContent{Text: fmt.Sprintf("Result: %v", result)},
},
}, result, nil
}
// Register tool
mcp.AddTool(server, tool, handler)Adding Prompts
Prompts provide reusable message templates:
prompt := &mcp.Prompt{
Name: "code-review",
}
handler := func(ctx context.Context, req *sdkmcp.GetPromptRequest, args map[string]string) (*mcp.GetPromptResult, error) {
code := args["code"]
language := args["language"]
return &mcp.GetPromptResult{
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: &mcp.TextContent{
Text: fmt.Sprintf("Please review this %s code:\n\n%s", language, code),
},
},
},
}, nil
}
server.AddPrompt(prompt, handler)Adding Resources
Resources provide access to data that the model can read:
resource := &mcp.Resource{
URI: "file:///docs/readme.md",
Name: "README",
MimeType: "text/markdown",
}
handler := func(ctx context.Context, req *sdkmcp.ReadResourceRequest, uri string) (*mcp.ReadResourceResult, error) {
content, err := os.ReadFile("README.md")
if err != nil {
return nil, err
}
return &mcp.ReadResourceResult{
Contents: []mcp.ResourceContents{
{
URI: uri,
MimeType: "text/markdown",
Text: string(content),
},
},
}, nil
}
server.AddResource(resource, handler)Transport Options
SSE Transport (Default)
The SSE (Server-Sent Events) transport is the original MCP transport from the 2024-11-05 specification:
mcp:
useStreamable: false
sseEndpoint: /sseStreamable HTTP Transport
The newer Streamable HTTP transport from the 2025-03-26 specification provides better connection management:
mcp:
useStreamable: true
messageEndpoint: /messageRequest Metadata Bridge
For multi-tenant or request-context-aware tools, you can extract selected HTTP request metadata once at the transport boundary and read it from context.Context in handlers.
server := mcp.NewMcpServerWithOptions(c,
mcp.WithRequestMetadataExtractor(mcp.DefaultRequestMetadataExtractor),
)
handler := func(ctx context.Context, req *mcp.CallToolRequest, args SomeArgs) (*mcp.CallToolResult, any, error) {
tenant, _ := mcp.HeaderFromContext(ctx, "X-Tenant-Id")
traceID, _ := mcp.QueryFromContext(ctx, "trace")
scope, _ := mcp.PathFromContext(ctx, "scope")
_ = tenant
_ = traceID
_ = scope
return &mcp.CallToolResult{}, nil, nil
}Available helpers:
RequestMetadataFromContext(ctx)HeaderFromContext(ctx, key)QueryFromContext(ctx, key)PathFromContext(ctx, key)
Configuration Options
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | Server name (required, from RestConf) | |
host |
string | Server host (required, from RestConf) | |
port |
int | Server port (required, from RestConf) | |
mcp.name |
string | MCP server name (defaults to name) |
|
mcp.version |
string | 1.0.0 |
Server version |
mcp.useStreamable |
bool | false |
Use Streamable HTTP transport instead of SSE |
mcp.sseEndpoint |
string | /sse |
SSE endpoint path |
mcp.messageEndpoint |
string | /message |
Message endpoint path |
mcp.sseTimeout |
duration | 24h |
SSE connection timeout |
mcp.messageTimeout |
duration | 30s |
Message processing timeout |
mcp.cors |
[]string | Allowed CORS origins |
Examples
See the adhoc/mcp directory for a complete working example.
Official SDK Documentation
For more details on the underlying MCP SDK, see:
License
This implementation follows the go-zero project license (MIT).
File: tools/goctl/api/parser/readme.md
Api语法描述
api示例
/**
* api语法示例及语法说明
*/
// api语法版本
syntax = "v1"
// import literal
import "foo.api"
// import group
import (
"bar.api"
"foo/bar.api"
)
info(
author: "songmeizi"
date: "2020-01-08"
desc: "api语法示例及语法说明"
)
// type literal
type Foo{
Foo int `json:"foo"`
}
// type group
type(
Bar{
Bar int `json:"bar"`
}
)
// service block
@server(
jwt: Auth
group: foo
)
service foo-api{
@doc "foo"
@handler foo
post /foo (Foo) returns (Bar)
}api语法结构
- syntax语法声明
- import语法块
- info语法块
- type语法块
- service语法块
- 隐藏通道
温馨提示️
在以上语法结构中,各个语法块从语法上来说,按照语法块为单位,可以在.api文件中任意位置声明,
但是为了提高阅读效率,我们建议按照以上顺序进行声明,因为在将来可能会通过严格模式来控制语法块的顺序。
syntax语法声明
syntax是新加入的语法结构,该语法的引入可以解决:
- 快速针对api版本定位存在问题的语法结构
- 针对版本做语法解析
- 防止api语法大版本升级导致前后不能向前兼容
警告 ⚠️
被import的api必须要和main api的syntax版本一致。
语法定义
'syntax'={checkVersion(p)}STRING语法说明
syntax:固定token,标志一个syntax语法结构的开始
checkVersion:自定义go方法,检测
STRING是否为一个合法的版本号,目前检测逻辑为,STRING必须是满足(?m)"v[1-9][0-9]*"正则。STRING:一串英文双引号包裹的字符串,如"v1"
一个api语法文件只能有0或者1个syntax语法声明,如果没有syntax,则默认为v1版本
正确语法示例 ✅
eg1:不规范写法
syntax="v1"eg2:规范写法(推荐)
syntax = "v2"错误语法示例 ❌
eg1:
syntax = "v0"eg2:
syntax = v1eg3:
syntax = "V1"import语法块
随着业务规模增大,api中定义的结构体和服务越来越多,所有的语法描述均为一个api文件,这是多么糟糕的一个问题, 其会大大增加了阅读难度和维护难度,import语法块可以帮助我们解决这个问题,通过拆分api文件,
不同的api文件按照一定规则声明,可以降低阅读难度和维护难度。
警告 ⚠️
这里import不像golang那样包含package声明,仅仅是一个文件路径的引入,最终解析后会把所有的声明都汇聚到一个spec.Spec中。
不能import多个相同路径,否则会解析错误。
语法定义
'import' {checkImportValue(p)}STRING
|'import' '(' ({checkImportValue(p)}STRING)+ ')'语法说明
import:固定token,标志一个import语法的开始
checkImportValue:自定义go方法,检测
STRING是否为一个合法的文件路径,目前检测逻辑为,STRING必须是满足(?m)"(/?[a-zA-Z0-9_#-])+\.api"正则。STRING:一串英文双引号包裹的字符串,如"foo.api"
正确语法示例 ✅
eg:
import "foo.api"
import "foo/bar.api"
import(
"bar.api"
"foo/bar/foo.api"
)错误语法示例 ❌
eg:
import foo.api
import "foo.txt"
import (
bar.api
bar.api
)info语法块
info语法块是一个包含了多个键值对的语法体,其作用相当于一个api服务的描述,解析器会将其映射到spec.Spec中, 以备用于翻译成其他语言(golang、java等)
时需要携带的meta元素。如果仅仅是对当前api的一个说明,而不考虑其翻译 时传递到其他语言,则使用简单的多行注释或者java风格的文档注释即可,关于注释说明请参考下文的 隐藏通道。
警告 ⚠️
不能使用重复的key,每个api文件只能有0或者1个info语法块
语法定义
'info' '(' (ID {checkKeyValue(p)}VALUE)+ ')'语法说明
info:固定token,标志一个info语法块的开始
checkKeyValue:自定义go方法,检测
VALUE是否为一个合法值。VALUE:key对应的值,可以为单行的除'\r','\n','/'后的任意字符,多行请以""包裹,不过强烈建议所有都以""包裹
正确语法示例 ✅
eg1:不规范写法
info(
foo: foo value
bar:"bar value"
desc:"long long long long
long long text"
)eg2:规范写法(推荐)
info(
foo: "foo value"
bar: "bar value"
desc: "long long long long long long text"
)错误语法示例 ❌
eg1:没有key-value内容
info()eg2:不包含冒号
info(
foo value
)eg3:key-value没有换行
info(foo:"value")eg4:没有key
info(
: "value"
)eg5:非法的key
info(
12: "value"
)eg6:移除旧版本多行语法
info(
foo: >
some text
<
)type语法块
在api服务中,我们需要用到一个结构体(类)来作为请求体,响应体的载体,因此我们需要声明一些结构体来完成这件事情, type语法块由golang的type演变而来,当然也保留着一些golang type的特性,沿用golang特性有:
- 保留了golang内置数据类型
bool,int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,uintptr
,float32,float64,complex64,complex128,string,byte,rune, - 兼容golang struct风格声明
- 保留golang关键字
警告 ⚠️
- 不支持alias
- 不支持time.Time数据类型
- 结构体名称、字段名称、不能为golang关键字
语法定义
由于其和golang相似,因此不做详细说明,具体语法定义请在ApiParser.g4中查看typeSpec定义。
语法说明
参考golang写法
正确语法示例 ✅
eg1:不规范写法
type Foo struct{
Id int `path:"id"` // ①
Foo int `json:"foo"`
}
type Bar struct{
// 非导出型字段
bar int `form:"bar"`
}
type(
// 非导出型结构体
fooBar struct{
FooBar int
}
)eg2:规范写法(推荐)
type Foo{
Id int `path:"id"`
Foo int `json:"foo"`
}
type Bar{
Bar int `form:"bar"`
}
type(
FooBar{
FooBar int
}
)错误语法示例 ❌
eg
type Gender int // 不支持
// 非struct token
type Foo structure{
CreateTime time.Time // 不支持time.Time
}
// golang关键字 var
type var{}
type Foo{
// golang关键字 interface
Foo interface
}
type Foo{
foo int
// map key必须要golang内置数据类型
m map[Bar]string
}① tag说明
tag定义和golang中json tag语法一样,除了json tag外,go-zero还提供了另外一些tag来实现对字段的描述,
详情见下表。
tag表
tag key 描述 提供方 有效范围 示例 json json序列化tag golang request、response json:"fooo"path 路由path,如 /foo/:idgo-zero request path:"id"form 标志请求体是一个form(POST方法时)或者一个query(GET方法时 /search?name=keyword)go-zero request form:"name"tag修饰符
常见参数校验描述
tag key 描述 提供方 有效范围 示例 optional 定义当前字段为可选参数 go-zero request json:"name,optional"options 定义当前字段的枚举值,多个以竖线②隔开 go-zero request json:"gender,options=male"default 定义当前字段默认值 go-zero request json:"gender,default=male"range 定义当前字段数值范围 go-zero request json:"age,range=[0:120]"② 竖线:|
温馨提示
tag修饰符需要在tag value后以引文逗号,隔开
service语法块
service语法块用于定义api服务,包含服务名称,服务metadata,中间件声明,路由,handler等。
警告 ⚠️
- main api和被import的api服务名称必须一致,不能出现服务名称歧义。
- handler名称不能重复
- 路由(请求方法+请求path)名称不能重复
- 请求体必须声明为普通(非指针)struct,响应体做了一些向前兼容处理,详请见下文说明
语法定义
serviceSpec: atServer? serviceApi;
atServer: '@server' lp='(' kvLit+ rp=')';
serviceApi: {match(p,"service")}serviceToken=ID serviceName lbrace='{' serviceRoute* rbrace='}';
serviceRoute: atDoc? (atServer|atHandler) route;
atDoc: '@doc' lp='('? ((kvLit+)|STRING) rp=')'?;
atHandler: '@handler' ID;
route: {checkHttpMethod(p)}httpMethod=ID path request=body? returnToken=ID? response=replybody?;
body: lp='(' (ID)? rp=')';
replybody: lp='(' dataType? rp=')';
// kv
kvLit: key=ID {checkKeyValue(p)}value=LINE_VALUE;
serviceName: (ID '-'?)+;
path: (('/' (ID ('-' ID)*))|('/:' (ID ('-' ID)?)))+;语法说明
serviceSpec:包含了一个可选语法块
atServer和serviceApi语法块,其遵循序列模式(编写service必须要按照顺序,否则会解析出错)atServer: 可选语法块,定义key-value结构的server metadata,'@server'表示这一个server语法块的开始,其可以用于描述serviceApi或者route语法块,其用于描述不同语法块时有一些特殊关键key
需要值得注意,见 atServer关键key描述说明。serviceApi:包含了1到多个
serviceRoute语法块serviceRoute:按照序列模式包含了
atDoc,handler和routeatDoc:可选语法块,一个路由的key-value描述,其在解析后会传递到spec.Spec结构体,如果不关心传递到spec.Spec,
推荐用单行注释替代。handler:是对路由的handler层描述,可以通过atServer指定
handlerkey来指定handler名称,
也可以直接用atHandler语法块来定义handler名称atHandler:'@handler' 固定token,后接一个遵循正则
[_a-zA-Z][a-zA-Z_-]*)的值,用于声明一个handler名称route:路由,有
httpMethod、path、可选request、可选response组成,httpMethod是必须是小写。body:api请求体语法定义,必须要由()包裹的可选的ID值
replyBody:api响应体语法定义,必须由()包裹的struct、
array(向前兼容处理,后续可能会废弃,强烈推荐以struct包裹,不要直接用array作为响应体)kvLit: 同info key-value
serviceName: 可以有多个'-'join的ID值
path:api请求路径,必须以'/'或者'/:'开头,切不能以'/'结尾,中间可包含ID或者多个以'-'join的ID字符串
atServer关键key描述说明
修饰service时
| key | 描述 | 示例 |
|---|---|---|
| jwt | 声明当前service下所有路由需要jwt鉴权,且会自动生成包含jwt逻辑的代码 | jwt: Auth |
| group | 声明当前service或者路由文件分组 | group: login |
| middleware | 声明当前service需要开启中间件 | middleware: AuthMiddleware |
修饰route时
| key | 描述 | 示例 |
|---|---|---|
| handler | 声明一个handler | - |
正确语法示例 ✅
eg1:不规范写法
@server(
jwt: Auth
group: foo
middleware: AuthMiddleware
)
service foo-api{
@doc(
summary: foo
)
@server(
handler: foo
)
// 非导出型body
post /foo/:id (foo) returns (bar)
@doc "bar"
@handler bar
post /bar returns ([]int)// 不推荐数组作为响应体
@handler fooBar
post /foo/bar (Foo) returns // 可以省略'returns'
}eg2:规范写法(推荐)
@server(
jwt: Auth
group: foo
middleware: AuthMiddleware
)
service foo-api{
@doc "foo"
@handler: foo
post /foo/:id (Foo) returns (Bar)
}
service foo-api{
@handler ping
get /ping
@doc "foo"
@handler: bar
post /bar/:id (Foo)
}错误语法示例 ❌
// 不支持空的server语法块
@server(
)
// 不支持空的service语法块
service foo-api{
}
service foo-api{
@doc kkkk // 简版doc必须用英文双引号引起来
@handler foo
post /foo
@handler foo // 重复的handler
post /bar
@handler fooBar
post /bar // 重复的路由
// @handler和@doc顺序错误
@handler someHandler
@doc "some doc"
post /some/path
// handler缺失
post /some/path/:id
@handler reqTest
post /foo/req (*Foo) // 不支持除普通结构体外的其他数据类型作为请求体
@handler replyTest
post /foo/reply returns (*Foo) // 不支持除普通结构体、数组(向前兼容,后续考虑废弃)外的其他数据类型作为响应体
}隐藏通道
隐藏通道目前主要为空白符号,换行符号以及注释,这里我们只说注释,因为空白符号和换行符号我们目前拿来也无用。
单行注释
语法定义
'//' ~[\r\n]*语法说明
由语法定义可知道,单行注释必须要以//开头,内容为不能包含换行符
正确语法示例 ✅
// doc
// comment错误语法示例 ❌
// break
line commentsjava风格文档注释
语法定义
'/*' .*? '*/'语法说明
由语法定义可知道,单行注释必须要以/*开头,*/结尾的任意字符。
正确语法示例 ✅
/**
* java-style doc
*/错误语法示例 ❌
/*
* java-style doc */
*/Doc&Comment
如果想获取某一个元素的doc或者comment开发人员需要怎么定义?
Doc
我们规定上一个语法块(非隐藏通道内容)的行数line+1到当前语法块第一个元素前的所有注释(当行,或者多行)均为doc, 且保留了
//、/*、*/原始标记。
Comment
我们规定当前语法块最后一个元素所在行开始的一个注释块(当行,或者多行)为comment 且保留了
//、/*、*/原始标记。
语法块Doc和Comment的支持情况
| 语法块 | parent语法块 | Doc | Comment |
|---|---|---|---|
| syntaxLit | api | ✅ | ✅ |
| kvLit | infoSpec | ✅ | ✅ |
| importLit | importSpec | ✅ | ✅ |
| typeLit | api | ✅ | ❌ |
| typeLit | typeBlock | ✅ | ❌ |
| field | typeLit | ✅ | ✅ |
| key-value | atServer | ✅ | ✅ |
| atHandler | serviceRoute | ✅ | ✅ |
| route | serviceRoute | ✅ | ✅ |
以下为对应语法块解析后细带doc和comment的写法
// syntaxLit doc
syntax = "v1" // syntaxLit comment
info(
// kvLit doc
author: songmeizi // kvLit comment
)
// typeLit doc
type Foo {}
type(
// typeLit doc
Bar{}
FooBar{
// filed doc
Name int // filed comment
}
)
@server(
/**
* kvLit doc
* 开启jwt鉴权
*/
jwt: Auth /**kvLit comment*/
)
service foo-api{
// atHandler doc
@handler foo //atHandler comment
/*
* route doc
* post请求
* path为 /foo
* 请求体:Foo
* 响应体:Foo
*/
post /foo (Foo) returns (Foo) // route comment
}File: tools/goctl/config/readme.md
配置项管理
| 名称 | 是否可选 | 说明 |
|---|---|---|
| namingFormat | YES | 文件名称格式化符 |
naming-format
namingFormat可以用于对生成代码的文件名称进行格式化,和日期格式化符(yyyy-MM-dd)类似,在代码生成时可以根据这些配置项的格式化符进行格式化。
格式化符(gozero)
格式化符由go,zero组成,如常见的三种格式化风格你可以这样编写:
- lower:
gozero - camel:
goZero - snake:
go_zero
常见格式化符生成示例
源字符:welcome_to_go_zero
| 格式化符 | 格式化结果 | 说明 |
|---|---|---|
| gozero | welcometogozero | 小写 |
| goZero | welcomeToGoZero | 驼峰 |
| go_zero | welcome_to_go_zero | snake |
| Go#zero | Welcome#to#go#zero | #号分割Title类型 |
| GOZERO | WELCOMETOGOZERO | 大写 |
| _go#zero_ | _welcome#to#go#zero_ | 下划线做前后缀,并且#分割 |
错误格式化符示例
- go
- gOZero
- zero
- goZEro
- goZERo
- goZeRo
- tal
使用方法
目前可通过在生成api、rpc、model时通过--style参数指定format格式,如:
goctl api go test.api -dir . -style gozerogoctl rpc proto -src test.proto -dir . -style go_zerogoctl model mysql datasource -url="" -table="*" -dir ./snake -style GoZero默认值
当不指定-style时默认值为gozero
2. Official Technical Reference & Guides (zeromicro/zero-doc)
File: README.md
go-zero
English | 简体中文
1. 项目介绍
2. 项目文档
API文档
awesome系列
3. 微信交流群
File: Readme.md
go-zero
English | 简体中文
1. 项目介绍
2. 项目文档
API文档
awesome系列
3. 微信交流群
File: readme.md
go-zero
English | 简体中文
1. 项目介绍
2. 项目文档
API文档
awesome系列
3. 微信交流群
File: docs/README.md
DEPRECATED: PLEASE MOVE TO https://go-zero.dev
home: true
heroImage: /logo.png
actionText: 快速上手 →
actionLink: /zero/
heroText: Go Zero
tagline: 集成各种工程实践的 WEB 和 RPC 框架
sidebar: auto
features:
- title: 大道至简
details: 极简的 API 描述,一键生成各端代码 - title: 自动治理
details: 内建级联超时控制、限流、自适应熔断、自适应降载等微服务治理能力 - title: 工程哲学
details: 微服务治理和工具包
footer: MIT Licensed | Copyright © 2020-present GoZero
// 安装 go-zero
GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero
// 然后就可以开始你的微服务之旅了