脚手架

安装

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
gf init demo -u
# demo 项目名称
# -u 使用最新版

目录结构

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
# CLI tool, only in development environment.
# https://goframe.org/docs/cli
gfcli:
gen:
dao:
# mysql=数据库类型 root=数据库账号 123456=数据库密码 127.0.0.1=数据库host 3306=端口 gf_admin = 所选数据库名称
- 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
# https://goframe.org/docs/web/server-config-file-template
server:
address: ":8000"
openapiPath: "/api.json"
swaggerPath: "/swagger"

# https://goframe.org/docs/core/glog-config
logger:
level : "all"
stdout: true

# https://goframe.org/docs/core/gdb-config-file
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("账号已注册")
}
//获取创建成功的ID
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
}
//返回创建成功的用户ID
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