go-zero 新手完整从零搭建 API 教程

go-zero 新手完整从零搭建 API 教程

前置准备(必须先装好)

1. 安装 Go 语言

  1. 官网下载 Go 1.20+:https://go.dev/dl/
  2. 安装时一路下一步,自动配置环境变量
  3. 打开 cmd 验证:

bash

运行

复制代码
go version
# 输出版本号即成功

2. 安装 go-zero 工具链(2 个核心工具)

打开终端执行:

bash

运行

复制代码
# 安装go-zero框架核心
go get github.com/zeromicro/go-zero@latest

# 代码生成工具 goctl(最重要,自动生成CRUD/API代码)
go install github.com/zeromicro/go-zero/tools/goctl@latest

3. 验证工具是否安装成功

新开终端输入:

bash

运行

复制代码
goctl version
# 输出版本号代表安装完成

4. 配置 Go 国内代理(Windows 必配,否则下载超时)

bash

运行

复制代码
go env -w GOPROXY=https://goproxy.cn,direct

一、完整步骤:快速创建 HTTP API 服务

步骤 1:创建项目文件夹,初始化 go mod

  1. 找一个空目录,比如 E:\go-project\user-api
  2. cmd 进入该目录,执行模块初始化

bash

运行

复制代码
# user-api 是你的模块名,统一项目内导入用
go mod init user-api

步骤 2:编写 API 描述文件(.api 文件,go-zero 专用)

在目录新建文件 user.api,复制下面完整内容(用户增删改查示例接口)

api

复制代码
syntax = "v1"

info (
	title:  "用户服务API"
	desc:   "演示go-zero http接口"
	author: "student"
)

type BaseResp {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data,omitempty"`
}

type GetUserReq {
	Id int64 `path:"id"`
}

type CreateUserReq {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

type UserResp {
	Id   int64  `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

type GetUserResp {
	Code int      `json:"code"`
	Msg  string   `json:"msg"`
	Data UserResp `json:"data,omitempty"`
}

service user-api {
	// 接口1
	@doc "根据id获取用户"
	@handler GetUserHandler
	get /user/:id (GetUserReq) returns (GetUserResp)

	// 接口2
	@doc "新增用户"
	@handler CreateUserHandler
	post /user (CreateUserReq) returns (BaseResp)
}

步骤 3:用 goctl 一键生成完整代码

终端执行生成命令(自动生成路由、handler、配置、main 入口)

bash

运行

复制代码
goctl api go -api user.api -dir .

执行完目录自动生成这些文件:

plaintext

复制代码
├── etc
│   └── user-api.yaml  # 服务配置文件(端口、超时等)
├── internal
│   ├── handler        # 接口逻辑处理器
│   │   └── userhandler.go
│   ├── logic          # 业务逻辑层(你主要写代码的地方)
│   │   └── userlogic.go
│   ├── svc            # 全局依赖上下文
│   │   └── servicecontext.go
│   └── types          # api自动解析的结构体
│       └── types.go
├── user.api
├── userapi.go         # main函数入口
└── go.mod

步骤 4:修改业务逻辑(写接口返回数据)

打开 internal/logic/userlogic.go

1)获取用户接口 GetUserLogic

找到 GetUser 方法,替换代码:

go

运行

复制代码
// 根据id获取用户
func (l *GetUserLogic) GetUser(req *types.GetUserReq) (resp *types.GetUserResp, err error) {
	// 模拟数据库查询
	user := types.UserResp{
		Id:   req.Id,
		Name: "测试用户",
		Age:  22,
	}
	return &types.GetUserResp{
		Code: 0,
		Msg:  "success",
		Data: user,
	}, nil
}

2)新增用户接口 CreateUserLogic

找到 CreateUser 方法:

go

运行

复制代码
func (l *CreateUserLogic) CreateUser(req *types.CreateUserReq) (resp *types.BaseResp, err error) {
	return &types.BaseResp{
		Code: 0,
		Msg:  fmt.Sprintf("新增用户成功,姓名:%s,年龄:%d", req.Name, req.Age),
	}, nil
}

文件顶部要导入 fmt:

go

运行

复制代码
import "fmt"

步骤 5:查看配置文件 etc/user-api.yaml

yaml

复制代码
Name: user-api
Host: 0.0.0.0
Port: 8888  # 服务监听端口

默认端口 8888,想改端口直接改这里数字。

步骤 6:下载依赖(自动拉取 go-zero)

bash

运行

复制代码
go mod tidy

步骤 7:启动 API 服务

bash

运行

复制代码
go run user.go -f etc/user-api.yaml

输出日志代表启动成功:

plaintext

复制代码
Starting server at 0.0.0.0:8888...

这个终端窗口不能关,关了服务停止

步骤 8:测试接口(新开 cmd 窗口)

测试 1:GET 查询用户

bash

运行

复制代码
curl http://127.0.0.1:8888/user/100

返回结果:

json

复制代码
{"code":0,"msg":"success","data":{"id":100,"name":"测试用户","age":22}}

测试 2:POST 新增用户

bash

运行

复制代码
curl -X POST -H "Content-Type:application/json" -d "{\"name\":\"张三\",\"age\":20}" http://127.0.0.1:8888/user

返回:

json

复制代码
{"code":0,"msg":"新增用户成功,姓名:张三,年龄:20"}

二、关键目录分层讲解(新手必懂)

  1. user.api:接口定义文件,统一管理路由、入参、出参,改完可一键重生成代码
  2. etc/*.yaml:配置中心,端口、数据库、etcd、redis 全部写在这里
  3. userapi.go:程序入口 main,只做初始化,不写业务
  4. internal/svc:全局资源(DB、Redis、etcd 客户端统一放这里初始化)
  5. internal/handler:接收 http 请求,参数校验,转发给 logic 层(不用改)
  6. internal/logic业务逻辑层,所有业务代码写这里
  7. internal/types:自动生成的请求返回结构体

三、常见新手踩坑解决

1. goctl 不是内部命令

原因:go 安装目录 bin 没加入系统 PATH 解决:关闭所有终端重新打开;重启电脑

2. go mod tidy 下载超时

执行代理配置:

bash

运行

复制代码
go env -w GOPROXY=https://goproxy.cn,direct

3. 端口 8888 被占用

修改 etc/user-api.yaml 里 Port 为 8889/9000 等

4. curl 不是内部命令(Windows)

方案 1:使用 PowerShell 自带 Invoke-WebRequest

powershell

复制代码
Invoke-WebRequest http://127.0.0.1:8888/user/100

方案 2:下载 Git Bash,自带 curl

5. 修改 api 文件后如何同步更新代码

重新执行生成命令,不会覆盖 logic 业务代码:

bash

运行

复制代码
goctl api go -api user.api -dir .

四、扩展:整合你前面学的 etcd(简单演示)

1. 修改配置 etc/user-api.yaml,增加 etcd 地址

yaml

复制代码
Name: user-api
Host: 0.0.0.0
Port: 8888
Etcd:
  Hosts:
    - 127.0.0.1:2379
  Key: user-api

2. 新建配置结构体 internal/config/config.go

go

运行

复制代码
package config

import (
	"github.com/zeromicro/go-zero/core/stores/etcd"
)

type Config struct {
	zrpc.RpcServerConf
	Etcd etcd.EtcdConf
}

3. servicecontext.go 注入 etcd 客户端

go

运行

复制代码
package svc

import (
	"user-api/internal/config"
	"github.com/zeromicro/go-zero/core/stores/etcd"
)

type ServiceContext struct {
	Config config.Config
	EtcdCli *etcd.EtcdClient
}

func NewServiceContext(c config.Config) *ServiceContext {
	cli := etcd.MustNewEtcdClient(c.Etcd)
	return &ServiceContext{
		Config: c,
		EtcdCli: cli,
	}
}

之后在 logic 层就能直接操作 etcd 读写配置、注册服务。

备注说明,设计user.api的内容解读

复制代码
// 指定api语法版本v1,标识文件解析标准
syntax = "v1"

// 接口文档基础信息块,生成swagger文档时读取这里内容展示
info (
	title:  "用户服务API"        // 接口文档标题
	desc:   "演示go-zero http接口" // 服务功能描述
	author: "student"            // 文档作者
)

// 全局统一返回结构体,作为通用返回模板
type BaseResp {
	Code int         `json:"code"`        // 业务状态码,0代表成功,非0代表业务错误
	Msg  string      `json:"msg"`         // 接口返回提示信息
	Data interface{} `json:"data,omitempty"` // 承载业务数据,无数据时json不序列化该字段
}

// 获取用户接口入参结构体
type GetUserReq {
	Id int64 `path:"id"` // path标签:参数从url路径 /user/:id 中获取
}

// 新增用户接口入参结构体
type CreateUserReq {
	Name string `json:"name"` // json标签:从请求body的json读取参数
	Age  int    `json:"age"`
}

// 用户业务实体,存放用户基础字段
type UserResp {
	Id   int64  `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// 查询用户专用返回体,嵌套用户实体
type GetUserResp {
	Code int      `json:"code"`
	Msg  string   `json:"msg"`
	Data UserResp `json:"data,omitempty"` // Data字段存放完整用户信息
}

// 定义HTTP服务,服务标识为user-api,所有接口写在{}内
service user-api {
	// 单行注释,仅开发查看,不会进入接口文档
	// 接口1
	@doc "根据id获取用户"       // swagger接口描述,对外展示接口功能
	@handler GetUserHandler     // 生成的业务处理函数名称,该接口逻辑写在此方法内
	get /user/:id (GetUserReq) returns (GetUserResp) 
	// get 请求方式;/user/:id 路由;GetUserReq 请求参数;GetUserResp 响应结构体

	// 接口2
	@doc "新增用户"
	@handler CreateUserHandler // 新增用户接口的处理函数名
	post /user (CreateUserReq) returns (BaseResp)
	// post提交新增数据;入参CreateUserReq;使用通用返回体BaseResp返回
}