go-zero Documentation

A cloud-native Go microservices framework with cli tool for productivity.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy go-zero on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name go-zero --restart always zeromicro/go-zero:latest

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?

English | 简体中文 | 한국어


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:

shell
go get -u github.com/zeromicro/go-zero

AI-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

bash
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  # Update

Cursor

bash
git submodule add https://github.com/zeromicro/ai-context.git .cursorrules
git submodule update --remote .cursorrules  # Update

Windsurf

bash
git submodule add https://github.com/zeromicro/ai-context.git .windsurfrules
git submodule update --remote .windsurfrules  # Update

Claude Desktop

bash
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-zero

How It Works

AI assistants use these tools together:

  1. ai-context - workflow guidance
  2. zero-skills - implementation patterns
  3. 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

  1. Full examples:

    Rapid development of microservice systems

    Rapid development of microservice systems - multiple RPCs

  2. 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 --help

    Ensure goctl is executable and in your $PATH.

  3. Create the API file (greet.api):

    go
    type (
      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:

    shell
    goctl api -o greet.api
  4. Generate Go server code

    shell
    goctl api go -api greet.api -dir greet

    Generated 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 file

    Run the service:

    shell
    cd greet
    go mod tidy
    go run greet.go -f etc/greet-api.yaml

    Default port: 8888 (configurable in etc/greet-api.yaml)

    Test with curl:

    shell
    curl -i http://localhost:8888/greet/from/you

    Response:

    http
    HTTP/1.1 200 OK
    Date: Sun, 30 Aug 2020 15:32:35 GMT
    Content-Length: 0
  5. Write business logic

    • Pass dependencies (mysql, redis, etc.) via servicecontext.go
    • Add logic code in the logic package per .api definition
  6. Generate client code for multiple languages

    shell
    goctl api java -api greet.api -dir greet
    goctl api dart -api greet.api -dir greet
    ...

Benchmark

Checkout the test code

Documents

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?

English | 简体中文 | 한국어


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:

shell
go get -u github.com/zeromicro/go-zero

AI-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

bash
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  # Update

Cursor

bash
git submodule add https://github.com/zeromicro/ai-context.git .cursorrules
git submodule update --remote .cursorrules  # Update

Windsurf

bash
git submodule add https://github.com/zeromicro/ai-context.git .windsurfrules
git submodule update --remote .windsurfrules  # Update

Claude Desktop

bash
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-zero

How It Works

AI assistants use these tools together:

  1. ai-context - workflow guidance
  2. zero-skills - implementation patterns
  3. 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

  1. Full examples:

    Rapid development of microservice systems

    Rapid development of microservice systems - multiple RPCs

  2. 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 --help

    Ensure goctl is executable and in your $PATH.

  3. Create the API file (greet.api):

    go
    type (
      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:

    shell
    goctl api -o greet.api
  4. Generate Go server code

    shell
    goctl api go -api greet.api -dir greet

    Generated 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 file

    Run the service:

    shell
    cd greet
    go mod tidy
    go run greet.go -f etc/greet-api.yaml

    Default port: 8888 (configurable in etc/greet-api.yaml)

    Test with curl:

    shell
    curl -i http://localhost:8888/greet/from/you

    Response:

    http
    HTTP/1.1 200 OK
    Date: Sun, 30 Aug 2020 15:32:35 GMT
    Content-Length: 0
  5. Write business logic

    • Pass dependencies (mysql, redis, etc.) via servicecontext.go
    • Add logic code in the logic package per .api definition
  6. Generate client code for multiple languages

    shell
    goctl api java -api greet.api -dir greet
    goctl api dart -api greet.api -dir greet
    ...

Benchmark

Checkout the test code

Documents

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?

English | 简体中文 | 한국어


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:

shell
go get -u github.com/zeromicro/go-zero

AI-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

bash
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  # Update

Cursor

bash
git submodule add https://github.com/zeromicro/ai-context.git .cursorrules
git submodule update --remote .cursorrules  # Update

Windsurf

bash
git submodule add https://github.com/zeromicro/ai-context.git .windsurfrules
git submodule update --remote .windsurfrules  # Update

Claude Desktop

bash
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-zero

How It Works

AI assistants use these tools together:

  1. ai-context - workflow guidance
  2. zero-skills - implementation patterns
  3. 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

  1. Full examples:

    Rapid development of microservice systems

    Rapid development of microservice systems - multiple RPCs

  2. 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 --help

    Ensure goctl is executable and in your $PATH.

  3. Create the API file (greet.api):

    go
    type (
      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:

    shell
    goctl api -o greet.api
  4. Generate Go server code

    shell
    goctl api go -api greet.api -dir greet

    Generated 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 file

    Run the service:

    shell
    cd greet
    go mod tidy
    go run greet.go -f etc/greet-api.yaml

    Default port: 8888 (configurable in etc/greet-api.yaml)

    Test with curl:

    shell
    curl -i http://localhost:8888/greet/from/you

    Response:

    http
    HTTP/1.1 200 OK
    Date: Sun, 30 Aug 2020 15:32:35 GMT
    Content-Length: 0
  5. Write business logic

    • Pass dependencies (mysql, redis, etc.) via servicecontext.go
    • Add logic code in the logic package per .api definition
  6. Generate client code for multiple languages

    shell
    goctl api java -api greet.api -dir greet
    goctl api dart -api greet.api -dir greet
    ...

Benchmark

Checkout the test code

Documents

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

English | 简体中文 | 한국어

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.

  1. product service - query product attributes
  2. inventory service - query inventory properties
  3. price service - query price attributes
  4. 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:

  1. querying product details: supporting concurrent calls to multiple services to combine product attributes, and supporting call errors that can be ended immediately.
  2. 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.

  1. data production generate
  2. data processing mapper
  3. 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.

go
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

English | 简体中文 | 한국어

为什么需要 MapReduce

在实际的业务场景中我们常常需要从不同的 RPC 服务中获取相应属性来组装成复杂对象。

比如要查询商品详情:

  1. 商品服务-查询商品属性
  2. 库存服务-查询库存属性
  3. 价格服务-查询价格属性
  4. 营销服务-查询营销属性

如果是串行调用的话响应时间会随着 RPC 调用次数呈线性增长,所以我们要优化性能一般会将串行改并行。

简单的场景下使用 WaitGroup 也能够满足需求,但是如果我们需要对 RPC 调用返回的数据进行校验、数据加工转换、数据汇总呢?继续使用 WaitGroup 就有点力不从心了,go 的官方库中并没有这种工具(java 中提供了 CompletableFuture),我们依据 MapReduce 架构思想实现了进程内的数据批处理 MapReduce 并发工具类。

设计思路

我们尝试把自己代入到作者的角色梳理一下并发工具可能的业务场景:

  1. 查询商品详情:支持并发调用多个服务来组合产品属性,支持调用错误可以立即结束。
  2. 商品详情页自动推荐用户卡券:支持并发校验卡券,校验失败自动剔除,返回全部卡券。

以上实际都是在进行对输入数据进行处理最后输出清洗后的数据,针对数据处理有个非常经典的异步模式:生产者消费者模式。于是我们可以抽象一下数据批处理的生命周期,大致可以分为三个阶段:

  1. 数据生产 generate
  2. 数据加工 mapper
  3. 数据聚合 reducer

其中数据生产是不可或缺的阶段,数据加工、数据聚合是可选阶段,数据生产与加工支持并发调用,数据聚合基本属于纯内存操作单协程即可。

再来思考一下不同阶段之间数据应该如何流转,既然不同阶段的数据处理都是由不同 goroutine 执行的,那么很自然的可以考虑采用 channel 来实现 goroutine 之间的通信。

如何实现随时终止流程呢?

goroutine 中监听一个全局的结束 channel 和调用方提供的 ctx 就行。

简单示例

并行求平方和(不要嫌弃示例简单,只是模拟并发)

go
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

English | 简体中文 | 한국어

logx configurations

go
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. on volume mode, the name is used to generate the log files. Within rest/zrpc services, the name will be set to the name of rest or zrpc automatically.
  • Mode: the mode to output the logs, default is console.
    • console mode writes the logs to stdout/stderr.
    • file mode writes the logs to the files specified by Path.
    • volume mode is used in docker, to write logs into mounted volumes.
  • Encoding: indicates how to encode the logs, default is json.
    • json mode writes the logs in json format.
    • plain mode writes the logs with plain text, with terminal color enabled.
  • TimeFormat: customize the time format, optional. Default is 2006-01-02T15:04:05.000Z07:00.
  • Path: set the log path, default to logs.
  • Level: the logging level to filter logs. Default is info.
    • info, all logs are written.
    • error, info logs are suppressed.
    • severe, info and error logs are suppressed, only severe logs are written.
  • Compress: whether or not to compress log files, only works with file mode.
  • 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 on console mode.
  • 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 when Rotation is size. NOTE: the level of option KeepDays will be higher. Even though MaxBackups sets 0, log files will still be removed if the KeepDays limitation is reached.
  • MaxSize: represents how much space the writing log file takes up. 0 means no limit. The unit is MB. Only take effect when Rotation is size.
  • Rotation: represents the type of log rotation rule. Default is daily.
    • daily rotate the logs by day.
    • size rotate the logs by size of logs.

Logging methods

go
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 like fmt.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 given key:value fields.
  • WithContext: inject the given ctx into the log messages, typically used to log trace-id and span-id.
  • WithDuration: write elapsed duration into the log messages, with key duration.

Integrating with third-party logging libs

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:

go
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:

go
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

English | 简体中文 | 한국어

logx 配置

go
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:输出日志的模式,默认是 console
    • console 模式将日志写到 stdout/stderr
    • file 模式将日志写到 Path 指定目录的文件中
    • volume 模式在 docker 中使用,将日志写入挂载的卷中
  • Encoding: 指示如何对日志进行编码,默认是 json
    • json模式以 json 格式写日志
    • plain模式用纯文本写日志,并带有终端颜色显示
  • TimeFormat:自定义时间格式,可选。默认是 2006-01-02T15:04:05.000Z07:00
  • Path:设置日志路径,默认为 logs
  • Level: 用于过滤日志的日志级别。默认为 info
    • info,所有日志都被写入
    • 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 按日志大小轮转。

打印日志方法

go
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(...) 来转换为 string
  • Errorf, Infof, Slowf: 将指定格式的信息写入日志
  • Errorv, Infov, Slowv: 将任何类型的信息写入日志,用 json marshal 编码
  • Errorw, Infow, Sloww: 写日志,并带上给定的 key:value 字段
  • WithContext:将给定的 ctx 注入日志信息,例如用于记录 trace-id和span-id
  • WithDuration: 将指定的时间写入日志信息中,字段名为 duration

与第三方日志库集成

对于其它的日志库,请参考上面示例实现,并欢迎提交 PR 到 https://github.com/zeromicro/zero-contrib

将日志写到指定的存储

logx定义了两个接口,方便自定义 logx,将日志写入任何存储。

  • logx.NewWriter(w io.Writer)
  • logx.SetWriter(write logx.Writer)

例如,如果我们想把日志写进kafka,而不是控制台或文件,我们可以像下面这样做。

go
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 字段被记录下来,我们可以像下面这样实现。

go
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

  1. Define a config structure, like below:
go
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)"`
}
  1. Write the yaml, toml or json config file:
  • yaml example
yaml
# most fields are optional or have default values
port: 8080
logMode: console
# you can use env settings
maxBytes: ${MAX_BYTES}
  • toml example
toml
# most fields are optional or have default values
port = 8_080
logMode = "console"
# you can use env settings
maxBytes = "${MAX_BYTES}"
  1. Load the config from a file:
go
// 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
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
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/Ping

Generate ProtoSet files

  • example command without external imports
shell
protoc --descriptor_set_out=hello.pb hello.proto
  • example command with external imports
shell
protoc --include_imports --proto_path=. --descriptor_set_out=hello.pb hello.proto

File: 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

bash
go get github.com/zeromicro/go-zero

Note: 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:

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:3000

3. Create Your Server

go
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:

go
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:

go
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:

go
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:

yaml
mcp:
  useStreamable: false
  sseEndpoint: /sse

Streamable HTTP Transport

The newer Streamable HTTP transport from the 2025-03-26 specification provides better connection management:

yaml
mcp:
  useStreamable: true
  messageEndpoint: /message

Request 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.

go
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示例

golang
/**
 * 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版本一致。

语法定义

antlrv4
'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:不规范写法

api
syntax="v1"

eg2:规范写法(推荐)

api
syntax = "v2"

错误语法示例 ❌

eg1:

api
syntax = "v0"

eg2:

api
syntax = v1

eg3:

api
syntax = "V1"

import语法块

随着业务规模增大,api中定义的结构体和服务越来越多,所有的语法描述均为一个api文件,这是多么糟糕的一个问题, 其会大大增加了阅读难度和维护难度,import语法块可以帮助我们解决这个问题,通过拆分api文件,
不同的api文件按照一定规则声明,可以降低阅读难度和维护难度。

警告 ⚠️

这里import不像golang那样包含package声明,仅仅是一个文件路径的引入,最终解析后会把所有的声明都汇聚到一个spec.Spec中。
不能import多个相同路径,否则会解析错误。

语法定义

antlrv4
'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:

api
import "foo.api"
import "foo/bar.api"

import(
    "bar.api"
    "foo/bar/foo.api"
)

错误语法示例 ❌

eg:

api
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语法块

语法定义

antlrv4
'info' '(' (ID {checkKeyValue(p)}VALUE)+ ')'

语法说明

info:固定token,标志一个info语法块的开始

checkKeyValue:自定义go方法,检测VALUE是否为一个合法值。

VALUE:key对应的值,可以为单行的除'\r','\n','/'后的任意字符,多行请以""包裹,不过强烈建议所有都以""包裹

正确语法示例 ✅

eg1:不规范写法

api
info(
foo: foo value
bar:"bar value"
    desc:"long long long long
long long text"
)

eg2:规范写法(推荐)

api
info(
    foo: "foo value"
    bar: "bar value"
    desc: "long long long long long long text"
)

错误语法示例 ❌

eg1:没有key-value内容

api
info()

eg2:不包含冒号

api
info(
    foo value
)

eg3:key-value没有换行

api
info(foo:"value")

eg4:没有key

api
info(
    : "value"
)

eg5:非法的key

api
info(
    12: "value"
)

eg6:移除旧版本多行语法

api
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:不规范写法

api
type Foo struct{
    Id int `path:"id"` // ①
    Foo int `json:"foo"`
}

type Bar struct{
    // 非导出型字段
    bar int `form:"bar"`
}

type(
    // 非导出型结构体
    fooBar struct{
        FooBar int
    }
)

eg2:规范写法(推荐)

api
type Foo{
    Id int `path:"id"`
    Foo int `json:"foo"`
}

type Bar{
    Bar int `form:"bar"`
}

type(
    FooBar{
        FooBar int
    }
)

错误语法示例 ❌

eg

api
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/:id go-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,响应体做了一些向前兼容处理,详请见下文说明

语法定义

antlrv4
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和route

atDoc:可选语法块,一个路由的key-value描述,其在解析后会传递到spec.Spec结构体,如果不关心传递到spec.Spec,
推荐用单行注释替代。

handler:是对路由的handler层描述,可以通过atServer指定handler key来指定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:不规范写法

api
@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:规范写法(推荐)

api
@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)
}

错误语法示例 ❌

api
// 不支持空的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) // 不支持除普通结构体、数组(向前兼容,后续考虑废弃)外的其他数据类型作为响应体
}

隐藏通道

隐藏通道目前主要为空白符号,换行符号以及注释,这里我们只说注释,因为空白符号和换行符号我们目前拿来也无用。

单行注释

语法定义

antlrv4
'//' ~[\r\n]*

语法说明
由语法定义可知道,单行注释必须要以//开头,内容为不能包含换行符

正确语法示例 ✅

api
// doc
// comment

错误语法示例 ❌

api
// break
line comments

java风格文档注释

语法定义

antlrv4
'/*' .*? '*/'

语法说明

由语法定义可知道,单行注释必须要以/*开头,*/结尾的任意字符。

正确语法示例 ✅

api
/**
 * java-style doc
 */

错误语法示例 ❌

api
/*
 * 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的写法

api
// 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格式,如:

shell script
goctl api go test.api -dir . -style gozero
shell script
goctl rpc proto -src test.proto -dir . -style go_zero
shell script
goctl 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. 项目文档

3. 微信交流群


File: Readme.md

go-zero

English | 简体中文





1. 项目介绍

2. 项目文档

3. 微信交流群


File: readme.md

go-zero

English | 简体中文





1. 项目介绍

2. 项目文档

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: 微服务治理和工具包
go
// 安装 go-zero
GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero

// 然后就可以开始你的微服务之旅了