首页 > 其他分享 >go-zero中api从入门到大师

go-zero中api从入门到大师

时间:2024-07-31 10:52:58浏览次数:15  
标签:文件 数据库 生成 goctl zero api go

api文件的学习

在go-zero中,api文件可以说是整个项目最重要的一个文件,学好它,写好他,项目相当于已经完成了一半!

接下来,我会详细说明.api是什么,以及怎么写

先给个案例:

type LoginRequest {
	UserName string `json:"userName"`
	Password string `json:"password"`
}

type UserLoginResponse {
	Token string `json:"Authorization"`
}

type UserInfoRequest {
	Authorization string `header:"Authorization"`
}

type UserInfoResponse {
	UserName string `json:"userName"`
	Id       uint   `json:"id"`
}

@server (
	group:      user //作用是将文件生成的文件夹根据group进行分组
	prefix:     user/v1 //前置路由路径:将该模块的所有路由都加上前缀
	middleware: DemoMiddleware
)
service user {
	@handler login
	post /api/users/login (LoginRequest) returns (UserLoginResponse)
}

@server (
	group:  userinfo //作用是将文件生成的文件夹根据group进行分组
	prefix: user/v1 //前置路由路径:将该模块的所有路由都加上前缀
	jwt:    Auth
)
service user {
	@handler userInfo
	get /api/users/info (UserInfoRequest) returns (UserInfoResponse)
}

// goctl api go -api v1.api -dir .

api文件由几部分组成:

类型定义: 定义了请求和响应的数据结构。

服务配置: 指定了服务的分组、前缀和中间件配置。

服务定义: 定义了具体的接口路径、请求方法、请求和响应的数据类型,以及处理该请求的处理器(hander)。

所以说,使用go-zero写代码之前就要先设计好该模块接口,并且写成.api文件

完成后就可以使用goctl生成代码框架了,

goctl命令语法:

goctl api go -api {API文件路径} -dir {生成代码的目标目录}

最佳实践:

我们可以创建该模块的目录,进入然后创建user.api文件,在该目录下执行生成命令(以user为例)

goctl api go -api user.api -dir .

一点一点分解:

image-20240729090434671

说到goctl,就先说下常用的goctl大全

goctl命令大全

生成 API 项目代码

goctl api go -api {API文件路径} -dir {生成代码的目标目录}

-api:指定 API 文件的路径。

-dir:指定生成代码的目标目录。

生成 API 文档

goctl api doc -o {输出文件路径} -api {API文件路径}

-o:指定输出文件的路径。

-api:指定 API 文件的路径。

生成 Markdown 格式的 API 文档

goctl api markdown -api {API文件路径} -dir {生成文档的目标目录}

根据 MySQL 表生成 Model

goctl model mysql datasource -url {数据源连接字符串} -table {表名} -dir {生成代码的目标目录}

根据 MySQL 表生成 CRUD 代码

goctl model mysql ddl -src {DDL文件路径} -dir {生成代码的目标目录} -c

创建 RPC 服务

goctl rpc new {服务名} --style {生成风格}

--style:生成风格,默认为 go-zero 推荐的风格。

生成 RPC 代码

goctl rpc proto -src {Proto文件路径} -dir {生成代码的目标目录}

(和生成api代码比较类似,用到最多的两个命令之一)

Template 命令

goctl template init --home {模板目录}

Docker 命令

goctl docker -go {Go文件路径} -o {输出Dockerfile路径} -c {Dockerfile模板路径}

Kubernetes 命令

goctl kube deploy -name {应用名称} -namespace {命名空间} -image {镜像名称} -o {输出文件路径}

再说会我们的api文件,生成后目录应该是这样子:

image-20240729091441380

我们如何去运行呢?因为运行需要main方法和yaml文件,生成的代码热心的帮我们把yaml文件的映射做好了,还帮忙做了配置文件默认路径:

image-20240729091624840

所以我们运行模块输入命令(进入模块根目录下):

go run user.go -f etc/users.yaml

按照步骤来,应该都可以运行的。。。

把每个文件中的代码都过一遍,按照mvc的逻辑来。

main.go

我们先看看main方法中的代码:

var configFile = flag.String("f", "etc/users.yaml", "the config file")

// f提供默认值为etc/users.yaml ,所以可以直接运行
func main() {
    flag.Parse()

    var c config.Config
    conf.MustLoad(*configFile, &c)

    server := rest.MustNewServer(c.RestConf) //初始化服务器实例
    defer server.Stop()                      //退出时关闭

    ctx := svc.NewServiceContext(c) //初始化程序:例如web中初始化数据库连接,初始化日志,消息队列等都放到这个文件中,数据库的model也会放到这个里
    handler.RegisterHandlers(server, ctx) //注册所有的 HTTP 路由和处理器

    fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
    server.Start()      //启动上边初始化的服务器实例
}

其实理解后会发现和其他web基本一样

然后看handler文件夹

handler

hander分为一个总router文件和按照api文件中分组的文件(不分组默认为service后的模块名)

image-20240729141725195

每一个接口都会有一个handler.go文件,分组是防止当接口太多时文件很乱。

接着看hander文件,其实可以理解为mvc架构中controller层的代码,

image-20240729142154853

解析传入参数调用逻辑层方法返回响应

注释:

func LoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 定义一个 LoginRequest 类型的变量,用于存储解析后的请求体数据
		var req types.LoginRequest

		// 使用 httpx.Parse 方法解析请求体,并将数据填充到 req 变量中
		if err := httpx.Parse(r, &req); err != nil {
			// 如果解析出现错误,返回错误响应
			httpx.ErrorCtx(r.Context(), w, err)
			return
		}

		// 创建一个新的 LoginLogic 实例,用于处理业务逻辑
		l := user.NewLoginLogic(r.Context(), svcCtx)

		// 调用 LoginLogic 的 Login 方法,传入解析后的请求数据
		resp, err := l.Login(&req)
		if err != nil {
			// 如果业务逻辑处理出现错误,返回错误响应
			httpx.ErrorCtx(r.Context(), w, err)
		} else {
			// 如果业务逻辑处理成功,返回 JSON 格式的响应数据
			httpx.OkJsonCtx(r.Context(), w, resp)
		}
	}
}

logic

真实的接口逻辑还是在logic层写的

image-20240729142907935

同样,一个接口对应一个文件,对该logic方法测试

image-20240729145616120

image-20240729145643748

说明是可以成功的,有人可能要问了,当使用get请求时,数据怎么发送?

需要在建立api文件时修改json为form,就可以做到在路径中发送了

image-20240729150800092

总结:get请求中发送query格式数据,将json改成form

image-20240729150913040

get请求中想将参数加入到路径中,再将form改成path

post请求中想将请求参数放到form-data中,需要将json改成form

post请求中想将请求参数方到路径中,需要改成path,并将service中路径加上 /:参数

image-20240729151217349

更多的基础设置可以到官方查看,写的非常清晰:

·image-20240729152307517

参数规则 | go-zero Documentation各种资料都有,官方不愧是国人。

然后是svc模块

svc

可能很多人没看懂svc是什么意思,他其实就是配置这个模块会用到的所有配置项,我们往常写web项目,方法传入参数都是需要什么传什么,(典型的就是contrller层,传入c context ,logic层传入几个指定参数…),然后将那些数据库全局初始化实例:db,Conn等作为全局变量供所有接口可以随意调用;

但是go-zero没有用这套,而是将所有参数合并到一个大的结构体中(ServiceContext),在几乎所有方法都是直接传入这个大结构体(handler和logic层都是传入ServiceContext),相当于每个接口都能访问所有定义好的参数。(这其中就包含了上下文C,数据库初始化对象UserModel等等)

image-20240730092516086

又有同学要问了,我之前那种模式用的好好的,为什么要改成这个样子?害得我又得学习。

这么做肯定是有很多优点的:

1. 集中管理
  • Go-zero: 在 Go-zero 中,所有的配置、数据库连接和业务逻辑所需的模型实例通常都被集中管理在 ServiceContext 中。这种方式确保了所有模块使用统一的配置和资源实例,避免了配置散布在不同地方的情况。
  • 传统方式: 传统的配置管理方式通常需要在多个地方(如全局变量、单例模式)进行配置和初始化。这可能导致配置的不一致性和重复的代码。
2. 提高模块化和解耦
  • Go-zero: ServiceContext 使得不同层(如 handler 层、logic 层、model 层)之间的依赖关系更加明确和集中。每个层只需依赖于 ServiceContext,而不需要直接处理底层的配置和初始化逻辑。
  • 传统方式: 在传统方式中,层之间可能直接依赖于具体的配置和资源,这会导致代码耦合度高,难以维护和扩展。
3. 简化依赖注入
  • Go-zero: 通过将 ServiceContext 作为参数传递给各个逻辑处理函数或结构体,可以简化依赖注入过程。每个函数或结构体只需要接收 ServiceContext,即可获取所需的所有配置和资源。
  • 传统方式: 传统的依赖注入通常需要复杂的构造函数或初始化代码来注入各种依赖。这可能导致依赖注入代码冗长且难以管理。
4. 统一资源管理
  • Go-zero: 资源(如数据库连接、缓存实例)在 ServiceContext 中进行集中管理。这使得资源的创建、配置和销毁都可以通过统一的入口进行管理,降低了资源泄漏或冲突的风险。
  • 传统方式: 传统的资源管理方式可能需要在不同的地方进行资源的创建和销毁,这可能导致资源的重复创建、未正确关闭或资源冲突等问题。
5. 易于测试
  • Go-zero: 使用 ServiceContext 可以更方便地进行单元测试。你可以创建一个包含模拟配置和模型实例的 ServiceContext,用于测试业务逻辑而不依赖于实际的数据库或外部服务。
  • 传统方式: 在传统方式中,由于配置和资源分散在代码的不同部分,测试时可能需要复杂的模拟和配置设置。
6. 增强代码的可读性和维护性
  • Go-zero: 通过将配置和资源集中在 ServiceContext 中,代码变得更加整洁和一致。每个组件只需关注其核心业务逻辑,其他方面的配置和资源管理由 ServiceContext 处理。
  • 传统方式: 传统的代码组织方式可能使得代码逻辑与配置管理混杂在一起,降低了代码的可读性和维护性。

我感觉这种方式最好的一个点是就是统一依赖注入,使开发者不用过多去关注传入参数的设置。

下一个文件夹config就不用多说了,写web都会用到,需要注意和yaml文件对应。

model

然后是model,自动生成代码时默认是不带这个文件夹的,但是当我们的项目需要用到数据库时,肯定是需要这个的,go-zero中默认在model文件夹中存储数据库映射的结构体和数据库CURD代码,而并不和之前写的model和数据库方法分离。

具体步骤是:使用api生成代码框架后,再使用model命令生成model然后才能开始开发。

生成model有两种方式,第一种是使用sql,指定sql文件的位置,生成sql语句对应的model和CURD。

**第二种是直接指定数据库的ip,用户名,密码,指定数据库,直接从数据库中获取DDL。**大家正常都会去使用第二种。

所以就讲一下第二种方式操作实例;

image-20240730141034507

具体步骤:照着上边的代码copy,放到项目根目录下(这个文件位置随意)

#!/usr/bin/env bash

# 使用方法:
# ./genModel.sh usercenter user
# ./genModel.sh usercenter user_auth

# 生成的表名
tables=$2
# 表生成的目录
modeldir=./genModel

# 数据库配置
host=127.0.0.1
port=3306
dbname=$1
#表示整个数据库里的
username=root
passwd=1234

echo "开始为数据库: $dbname 创建表 $tables 的模型"

# 使用 goctl 生成模型代码
goctl model mysql datasource -url="${username}:${passwd}@tcp(${host}:${port})/${dbname}" -table="${tables}" -dir="${modeldir}" --style=goZero

echo "模型生成完成,请将 ./genModel 目录下的文件移动到对应服务的 model 目录,并记得修改 package 名称。"

把数据库的几个字段换成自己的,若是window电脑,需要下载git bush,使用git的都有。然后在文件夹中:image-20240730153202283

打开git黑窗口,输入:

./genModel.sh  <数据库名>   <数据库表名>

就可以将对应的数据库文件生成到指定位置,我推荐是在该数据库的模块下新建一个model文件夹,将对应的数据库文件拷贝到其下,然后修改包名为model。

image-20240730153438911

到这里,mysql的model文件算是生成了,那怎么用呢?需要在config和yaml中同时加上数据库的配置

image-20240730153545931

image-20240730153553407

只要对照就行,主要是svc层中,需要将数据库初始化一下,

image-20240730153655886

按照这个格式写,可以去logic层测试是否成功,需要注意,调用数据库方法时,直接输入l.svcCtx.UserModel.FindOne

image-20240730153831566

就可以成功。

自动生成的CRUD都是围绕用户自己设置的数据库主键生成的。

到目前为止,整个纯api的go-zero项目基本就完全了,之后会说一些其他零碎知识点,rpc层的编写。

最后,我非常推荐大家去看go-zero的官方文档,看完就能上手,非常的详细

框架概述 | go-zero Documentation

标签:文件,数据库,生成,goctl,zero,api,go
From: https://blog.csdn.net/qq_63728673/article/details/140814307

相关文章

  • anki Windows 按下z键,使用有道api发音选中英文文本
     <scripttype="text/javascript"> //播放句子的函数 functionplaySentence(sentence){ //构造有道词典的在线朗读URL varyoudaoUrl="https://dict.youdao.com/dictvoice?audio="+encodeURIComponent(sentence); //创建音频元素并播放 varaudio=newAu......
  • 下一代 CLI 工具,使用Go语言用于构建令人惊叹的网络应用程序
    大家好,今天给大家分享一个创新的命令行工具GoweblyCLI,它专注于使用Go语言来快速构建现代Web应用程序。GoweblyCLI是一款免费开源软件,有助于在后端使用Go、在前端使用htmx和hyperscript以及最流行的CSS框架轻松构建令人惊叹的Web应用程序。CLI生成一个随时可用的......
  • ArgoCD 简介
    fork https://github.com/DevopsChina/lab/tree/main/deploy/lab04-argocd  1.ArgoCD简介基于kubernetes的声明式Gitops持续部署工具。持续部署工具有很多,如Jenkins等等,我们为什么选择ArgoCD呢?应用定义,配置和环境变量管理等等,都是声明式的,基于云原生的。......
  • Suno 歌曲生成 API 对接说明
    Suno歌曲生成API对接说明随着AI的应用变广,各类AI程序已逐渐普及。AI已逐渐深入到人们的工作生活方方面面。而AI涉及的行业也越来越多,从最初的写作,到医疗教育,再到现在的音乐。Suno是一个专业高质量的AI歌曲和音乐创作平台,用户只需输入简单的文本提示词,即可根......
  • 什么是Ego Status?
    在自动驾驶领域,“EgoStatus”通常指的是自动驾驶车辆自身的状态信息。这个术语是从机器人学和自动化领域借用的,其中“Ego”代表主体或“自我”,即自动驾驶车辆自身。以下是“EgoStatus”可能包含的一些具体信息:位置(Position):车辆在地图上的具体坐标。速度(Velocity):车辆移动......
  • 如何在 GoLand 中使用 gofmt 和 goimports 工具
    如何在GoLand中使用gofmt和goimports工具参考文章GoLand是JetBrains公司开发的一款Go语言集成开发环境(IDE),拥有丰富的代码自动补全、错误提示和代码重构等功能,极大地提高了编程效率。Go语言有一套自带的代码格式化工具——gofmt,它能够自动将非标准的Go代码格式化为......
  • go高并发之路——消息中间件kafka(上)
    一般高并发的业务都是某个时间段的请求量特别大,比如本人负责的直播业务,基本上一天就两个高峰段:早上和晚上的特定时间段。其它的时间里,流量基本都比较平稳。那么面对流量高峰,我们可以采取哪些措施呢?常见的有服务器和DB提前扩容、监控告警(盯监控)、流量削峰、加缓存、网关限流、服务......
  • Go语言---sort 包中sort.Ints()、sort.Strings()、sort.Slice()、sort.SliceStable()、s
    在每一种编程语言中,都会涉及到排序操作。而在Go语言中,其中内置的sort包中提供了根据一些排序函数来对任何序列进行排序的功能。通过这个包中的一些方法,我们可以对一些基本的可以比较大小的类型的切片进行排序,也可以通过实现排序接口的几个特定方法实现自定义排序。sort.I......
  • Python面试题:如何使用Django Rest Framework构建RESTful API
    使用DjangoRestFramework(DRF)构建RESTfulAPI是一个常见且强大的方法。以下是一个详细的指南,帮助你从头开始创建一个基本的Django项目,并使用DRF构建一个RESTfulAPI。环境准备安装Django和DjangoRestFramework:pipinstalldjangodjangorestframewor......
  • golang面试题:json包变量不加tag会怎么样?
    问题json包里使用的时候,结构体里的变量不加tag能不能正常转成json里的字段?怎么答如果变量首字母小写,则为private。无论如何不能转,因为取不到反射信息。如果变量首字母大写,则为public。不加tag,可以正常转为json里的字段,json内字段名跟结构体内字段原名一致。加了tag,从str......