go-zero 新手完整从零搭建 API 教程
前置准备(必须先装好)
1. 安装 Go 语言
- 官网下载 Go 1.20+:https://go.dev/dl/
- 安装时一路下一步,自动配置环境变量
- 打开 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
- 找一个空目录,比如
E:\go-project\user-api - 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"}
二、关键目录分层讲解(新手必懂)
user.api:接口定义文件,统一管理路由、入参、出参,改完可一键重生成代码etc/*.yaml:配置中心,端口、数据库、etcd、redis 全部写在这里userapi.go:程序入口 main,只做初始化,不写业务internal/svc:全局资源(DB、Redis、etcd 客户端统一放这里初始化)internal/handler:接收 http 请求,参数校验,转发给 logic 层(不用改)internal/logic:业务逻辑层,所有业务代码写这里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返回
}