脚手架
安装
1
| go install github.com/gogf/gf/cmd/gf/v2@latest
|
查看是否安装成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ gf -v v2.9.0 Welcome to GoFrame! Env Detail: Go Version: go1.24.3 windows/amd64 GF Version(go.mod): cannot find go.mod CLI Detail: Installed At: C:\Users\JT\go\bin\gf.exe Built Go Version: go1.24.3 Built GF Version: v2.9.0 Others Detail: Docs: https://goframe.org Now : 2025-08-27T15:18:41+08:00
|
模板
目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| demo ├── api ├── hack ├── internal │ ├── cmd │ ├── consts │ ├── controller │ ├── dao │ ├── model │ | ├── do │ │ └── entity │ └── service ├── manifest ├── resource ├── utility ├── go.mod └── main.go
|
目录说明
| 目录/文件名称 |
说明 |
描述 |
| api |
对外接口 |
对外提供服务的输入/输出数据结构定义。考虑到版本管理需要,往往以 api/xxx/v1… 存在 |
| hack |
工具脚本 |
存放项目开发工具、脚本等内容。例如, CLI 工具的配置,各种 shell/bat 脚本等文件 |
| internal |
内部逻辑 |
业务逻辑存放目录。通过 Golang internal 特性对外部隐藏可见性。 |
| - cmd |
入口指令 |
命令行管理目录。可以管理维护多个命令行。 |
| - consts |
常量定义 |
项目所有常量定义。 |
| - controller |
接口处理 |
接收/解析用户输入参数的入口/接口层。 |
| - dao |
数据访问 |
数据访问对象,这是一层抽象对象,用于和底层数据库交互,仅包含最基础的 CRUD 方法 |
| - model |
结构模型 |
数据结构管理模块,管理数据实体对象,以及输入与输出数据结构定义。 |
| - do |
领域对象 |
用于 dao 数据操作中业务模型与实例模型转换,由工具维护,用户不能修改。 |
| - entity |
数据模型 |
数据模型是模型与数据集合的一对一关系,由工具维护,用户不能修改。 |
| - service |
业务实现 |
业务逻辑的具体实现和封装。往往是项目中最复杂的部分。 |
| manifest |
交付清单 |
包含程序编译、部署、运行、配置的文件。常见内容如下: |
| - config |
配置管理 |
配置文件存放目录。 |
| - docker |
镜像文件 |
Docker 镜像相关依赖文件,脚本文件等等。 |
| - deploy |
部署文件 |
部署相关的文件。默认提供了 Kubernetes 集群化部署的 Yaml 模板,通过 kustomize |
| resource |
静态资源 |
静态资源文件。这些文件往往可以通过 资源打包/镜像编译 的形式注入到发布文件中。 |
| utility |
工具包 |
项目的工具包,提供了一些常用的工具函数。 |
| go.mod |
依赖管理 |
使用 Go Module 包管理的依赖描述文件。 |
| main.go |
入口文件 |
程序入口文件。 |
创建数据表
1 2 3 4 5 6 7 8 9 10 11
| CREATE TABLE `gf_user` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `username` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号', `nickname` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '昵称', `password` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', `status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '0=正常,1=禁用', `registTime` datetime DEFAULT NULL COMMENT '注册时间', `lastLoginTime` datetime DEFAULT NULL COMMENT '最后登录时间', PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
配置数据库
hack/config.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13
|
gfcli: gen: dao: - link: "mysql:root:123456@tcp(127.0.0.1:3306)/gf_admin" descriptionTag: true
docker: build: "-a amd64 -s linux -p temp -ew" tagPrefixes: - my.image.pub/my-app
|
mainfest/config/config.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| server: address: ":8000" openapiPath: "/api.json" swaggerPath: "/swagger"
logger: level : "all" stdout: true
database: default: link: "mysql:root:123456@tcp(127.0.0.1:3306)/gf_admin"
|
添加接口定义
api/user/va/user.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| package v1
import ( "demo/internal/model/entity" "github.com/gogf/gf/v2/frame/g" )
type CreateReq struct { g.Meta `path:"/user" method:"post" tags:"User" summary:"CreateUser"` Username string `v:"required|length:6,12" dc:"username"` Nickname string `v:"required|length:3,12" dc:"nickname"` Password string `v:"required" dc:"password"` }
type CreateRes struct { Id int64 `json:"id" dc:"user id"` }
type UpdateReq struct { g.Meta `path:"/user/{id}" method:"put" tags:"User" summary:"UpdateUser"` Id int64 `v:"required" dc:"user id"` Nickname string `v:"required" dc:"user nickname"` Password string `v:"required" dc:"user password"` }
type UpdateRes struct { }
type DeleteReq struct { g.Meta `path:"/user/{id}" method:"delete" tags:"User" summary:"DeleteUser"` Id int64 `v:"required" dc:"user id"` }
type DeleteRes struct { }
type GetOneReq struct { g.Meta `path:"/user/{id}" method:"get" tags:"User" summary:"GetUserInfo"` Id int64 `v:"required" dc:"user id"` }
type GetOneRes struct { *entity.GfUser `dc:"user"` }
type GetListReq struct { g.Meta `path:"/user" method:"get" tags:"User" summary:"Get User"` Status *uint8 `v:"in:0,1" dc:"user status"` }
type GetListRes struct { List []*entity.GfUser `json:"list" dc:"user list"` }
|
生成controller
1 2 3 4 5 6 7 8 9 10
| $ gf gen ctrl generated: demo/api/user/user.go generated: demo/internal/controller/user/user.go generated: demo/internal/controller/user/user_new.go generated: demo/internal/controller/user/user_v1_create.go generated: demo/internal/controller/user/user_v1_update.go generated: demo/internal/controller/user/user_v1_delete.go generated: demo/internal/controller/user/user_v1_get_one.go generated: demo/internal/controller/user/user_v1_get_list.go
|
接口定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # demo/api/user/user.go
package user
import ( "context"
"demo/api/user/v1" )
type IUserV1 interface { Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) Delete(ctx context.Context, req *v1.DeleteReq) (res *v1.DeleteRes, err error) GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error) GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # demo/internal/controller/user/user_new.go
package user
import ( "demo/api/user" )
type ControllerV1 struct{}
func NewV1() user.IUserV1 { return &ControllerV1{} }
|
创建用户实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| # demo/internal/controller/user/user_v1_create.go
package user
import ( "context" "demo/api/user/v1" "demo/internal/dao" "demo/internal/model/do" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/os/gtime" )
func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) { isExist, err := dao.GfUser.Ctx(ctx).Where("username", req.Username).Exist() if isExist != false { return nil, gerror.New("账号已注册") } insertId, err := dao.GfUser.Ctx(ctx).Data(do.GfUser{ Nickname: req.Nickname, Username: req.Username, Password: req.Password, RegistTime: gtime.Now(), LastLoginTime: gtime.Now(), }).InsertAndGetId() if err != nil { return nil, err } res = &v1.CreateRes{ Id: insertId, } return }
|
删除用户实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package user
import ( "context" "demo/internal/dao" "demo/internal/model/do" "github.com/gogf/gf/v2/errors/gerror"
"demo/api/user/v1" )
func (c *ControllerV1) Delete(ctx context.Context, req *v1.DeleteReq) (res *v1.DeleteRes, err error) { isExist, err := dao.GfUser.Ctx(ctx).Where(do.GfUser{Id: req.Id}).Exist() if isExist != true { return nil, gerror.Newf("用户ID:%d不存在", req.Id) }
result, err := dao.GfUser.Ctx(ctx).Where(do.GfUser{Id: req.Id}).Delete() if err != nil { return nil, err }
rowsAffected, err := result.RowsAffected() if err != nil { return nil, err } if rowsAffected == 0 { return nil, gerror.Newf("用户ID:%d删除失败", req.Id) } return &v1.DeleteRes{}, nil
}
|
修改用户实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package user
import ( "context" "demo/internal/dao" "demo/internal/model/do"
"github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror"
"demo/api/user/v1" )
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) { _, err = dao.GfUser.Ctx(ctx).Data(do.GfUser{ Password: req.Password, Nickname: req.Nickname, }).Where(do.GfUser{Id: req.Id}).Update() return nil, gerror.NewCode(gcode.CodeNotImplemented) }
|
查询用户实现(单个)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package user
import ( "context" "demo/internal/dao" "demo/internal/model/do"
"github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror"
"demo/api/user/v1" )
func (c *ControllerV1) GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error) { res = &v1.GetOneRes{} err = dao.GfUser.Ctx(ctx).Where(do.GfUser{Id: req.Id}).Scan(&res.GfUser) if err != nil { return nil, err } if res.GfUser.Id == 0 { return nil, gerror.NewCode(gcode.CodeNotImplemented) }
return }
|
查询用户实现(列表)
package user
import (
"context"
"demo/api/user/v1"
"demo/internal/dao"
"demo/internal/model/do"
)
// 获取用户列表8464w4
func (c *ControllerV1) GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error) {
res = &v1.GetListRes{}
err = dao.GfUser.Ctx(ctx).Data(do.GfUser{Id: req.Status}).Scan(&res.List)
if err != nil {
return nil, err
}
return
}
q