Gone框架介绍17 - 创建一个可运行在生产环境的Web项目

gone是可以高效开发Web服务的Golang依赖注入框架
github地址:https://github.com/gone-io/gone
文档原地址:https://goner.fun/zh/guide/auto-gen-priest.html
请帮忙在github上点个 ⭐️吧,这对我很重要 ;万分感谢!!

Web+MySQL

在本文中,我将演示如何创建一个可运行在生产环境的Web项目,并对项目做简单的介绍。项目的使用MySql作为数据库,使用docker-compose管理容器。

安装gone辅助工具

go install github.com/gone-io/gone/tools/gone@latest

关于gone命令,更多参考:gone辅助工具

使用gone命令创建项目

gone create -t web+mysql web-mysql-docker

上面命令会在当前目录中创建一个名为web-mysql-docker的目录。

编译并运行

假设你已经安装了make;如果没有安装请先安装,参考:安装make
建设你已经安装了dockerdocker compose;如果没有,参考: https://docs.docker.com/engine/install/。

执行系列命令

# 进入项目目录
cd web-mysql-docker

# 生成Priest函数:https://goner.fun/zh/guide/auto-gen-priest.html
make gone


# 启动MySql服务
docker compose up -d mysql

# 编译并运行
make run

日志打印如下:

➜  web-mysql-docker make run
make gone
make install-gone
go install github.com/gone-io/gone/tools/gone@latest
go mod tidy
go generate ./...
go run cmd/server/main.go
2024-05-14 12:42:03.574|INFO|Init|Revive github.com/gone-io/gone/heaven
2024-05-14 12:42:03.574|INFO|Init|Revive github.com/gone-io/gone/cemetery
2024-05-14 12:42:03.574|INFO|Init|Revive github.com/gone-io/gone/goner/tracer/tracer
2024-05-14 12:42:03.574|INFO|Init|Revive github.com/gone-io/gone/goner/logrus/logger
2024-05-14 12:42:03.574|INFO|Init|Revive github.com/gone-io/gone/goner/config/config
2024-05-14 12:42:03.574|INFO|Init|Revive github.com/gone-io/gone/goner/config/propertiesConfigure
2024-05-14 12:42:03.574|INFO|Init|Revive github.com/gone-io/gone/goner/logrus/logger
2024-05-14 12:42:03.574|INFO|Init|==>Use Env: local
2024-05-14 12:42:03.574|WARNING|Init|properties: /var/folders/jv/rn9b7nhs2ls1n1j_lqj005r80000gn/T/go-build521033176/b001/exe/config/default.properties not found. skipping
2024-05-14 12:42:03.574|WARNING|Init|properties: /var/folders/jv/rn9b7nhs2ls1n1j_lqj005r80000gn/T/go-build521033176/b001/exe/config/local.properties not found. skipping
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/config/config
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/config/propertiesConfigure
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/xorm/engine
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/cmux/server
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/gin/proxy
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/gin/router
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/gin/sysProcessor
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/gin/responser
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/gin/server
2024-05-14 12:42:03.575|INFO|Init|Revive github.com/gone-io/gone/goner/gin/httpInjector
2024-05-14 12:42:03.575|INFO|Init|Revive web-mysql/internal/controller/demoController
2024-05-14 12:42:03.575|INFO|Init|Revive web-mysql/internal/middleware/AuthorizeMiddleware
2024-05-14 12:42:03.575|INFO|Init|Revive web-mysql/internal/middleware/PubMiddleware
2024-05-14 12:42:03.575|INFO|Init|Revive web-mysql/internal/module/demo/db
2024-05-14 12:42:03.575|INFO|Init|Revive web-mysql/internal/module/demo/demoService
2024-05-14 12:42:03.575|INFO|Init|Revive web-mysql/internal/router/authRouter
2024-05-14 12:42:03.575|INFO|Init|Revive web-mysql/internal/router/pubRouter
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /api/demo/show            --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func5 (8 handlers)
[GIN-debug] GET    /api/demo2/show           --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func5 (7 handlers)
[GIN-debug] GET    /api/demo2/error          --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func5 (7 handlers)
[GIN-debug] GET    /api/demo2/echo           --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func5 (7 handlers)
[GIN-debug] GET    /api/inject-query         --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] GET    /api/inject/:key          --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] POST   /api/inject-http-body     --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] GET    /api/inject-http-struct   --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] POST   /api/users                --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] GET    /api/users                --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] GET    /api/users/page           --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] GET    /api/users/:id            --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] PUT    /api/users/:id            --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
[GIN-debug] DELETE /api/users/:id            --> github.com/gone-io/gone/goner/gin.(*proxy).Proxy.(*proxy).proxyOne.func8 (7 handlers)
2024-05-14 12:42:03.576|INFO|/Users/jim/go/pkg/mod/github.com/gone-io/gone@v0.3.1/goner/gin/server.go:46||Server Listen At :8080
2024-05-14 12:42:03.576|INFO|/Users/jim/go/pkg/mod/xorm.io/xorm@v1.3.2/log/logger_context.go:90||PING DATABASE mysql
2024-05-14 12:42:03.585|INFO|/Users/jim/go/pkg/mod/github.com/gone-io/gone@v0.3.1/cemetery.go:329||Revive [Anonymous Goner]
2024-05-14 12:42:03.585|INFO|/Users/jim/works/gone-io/web-app/demo/web-mysql-docker/cmd/server/main.go:28||before start

测试接口

我这里使用Goland内置Http Request插件测试。
使用Goland打开项目,打开文件tests/api/user.http,选择dev环境运行,如下:
请添加图片描述

执行结果:
请添加图片描述

项目简单介绍

目录结构

├── Dockerfile
├── Makefile
├── README.md
├── cmd
│   └── server
│       └── main.go #项目main方法所在文件
├── config          #项目配置目录
│   ├── default.properties #默认配置
│   ├── dev.properties     #开发环境配置
│   ├── local.properties   #本地环境配置
│   └── prod.properties    #生产环境配置
├── docker-compose.yaml    # docker-compose,定义了mysql 和 web 两个容器
├── go.mod
├── internal
│   ├── controller         #Controller
│   │   └── demo_ctr.go
│   ├── interface          #接口目录
│   │   ├── domain         #领域模型
│   │   │   ├── demo.go
│   │   │   ├── page.go
│   │   │   └── user.go
│   │   ├── entity         #实体模型
│   │   │   └── User.go
│   │   └── service        #服务接口
│   │       └── i_demo.go  #一个文件一般只放一个接口,文件名以`i_开口`,接口名以 `I`卡头,比如`IDemo`
│   ├── master.go
│   ├── middleware         #中间件目录,可以定义鉴权等统一处理逻辑
│   │   ├── authorize.go
│   │   └── pub.go
│   ├── module             #模块目录
│   │   └── demo           #demo模块
│   │       ├── db.go      #demo目录的数据库接口的实现
│   │       ├── demo_svc.go #demo Service,实现了`service.IDemo`接口
│   │       ├── error.go    # 当前目录错误码定义
│   │       └── i_db.go    #demo目录的数据库接口
│   ├── pkg                #公共工具目录
│   │   └── utils
│   │       └── error.go
│   ├── priest.go         #gone create 创建是没有该文件,运行 `make gone`生成的
│   └── router            #路由目录
│       ├── auth_router.go # 定义了需要鉴权的的路由组
│       └── pub_router.go  # 定义了无需鉴权的的路由组
├── scripts                # 脚本目录,用于存放一些脚本
│   └── mysql
│       └── initdb.d       #mysql initdb.d目录,docker-compose中定义的mysql首次启动时 会执行该目录下所有sql文件
│           └── user.sql
└── tests                  #集成测试目录
    └── api                #接口测试目录
        ├── demo.http
        ├── http-client.env.json
        └── user.http

项目特点

  • 开箱可用,无需额外配置直接可以运行
  • 生成了Dockerfile,方便部署到各种容器环境
  • 使用Makefile整合了gone、go、docker、docker compose等命令
  • 自动生成Priest函数,使开发更顺畅
  • 使用了gone框架,引入了依赖注入
  • 使用接口解耦
  • 支持分环境编写配置
  • 集成了MySQL数据库

部分代码讲解

//...
	// demo数据 user 的增删改查,挂载到authRouter只为方便演示
	ctr.
		pubRouter.
		Group("/users").
		POST("", func(in struct {
            //Body注入,根据contentType将HTTP正文解析为一个结构体,支持json、xml、form-data、x-www-form-urlencoded 等 contentType
			req *domain.User `gone:"http,body"`
		}) error {
			return ctr.demoSvc.CreateUser(in.req)
		}).
		GET("", func() (any, error) {
			return ctr.demoSvc.ListUsers()
		}).
		GET("/page", func(in struct {
			query domain.PageQuery `gone:"http,query"` //Query注入
		}) (any, error) {
			return ctr.demoSvc.PageUsers(in.query)
		}).
		GET("/:id", func(in struct {
			id int64 `gone:"http,param"`              //Url参数注入,将注入路由上定义的`:id`
		}) (any, error) {
			return ctr.demoSvc.GetUserById(in.id)
		}).
		PUT("/:id", func(in struct {
			id  int64        `gone:"http,param"` //Url参数注入,将注入路由上定义的`:id`
			req *domain.User `gone:"http,body"`  //Body注入
		}) error {
			return ctr.demoSvc.UpdateUserById(in.id, in.req)
		}).
		DELETE("/:id", func(in struct {
			id int64 `gone:"http,param"` //Url参数注入,将注入路由上定义的`:id`
		}) error {
			return ctr.demoSvc.DeleteUser(in.id)
		})
//...

上面代码截取于internal/controller/demo_ctr.go文件。

HTTP 注入

可以看到,Gone在路由处理函数上也支持了依赖注入;注入的方式是在使用一个匿名结构体作为处理函数的入参,并给结构体属性做特殊标记。
上面代码用的注入标签:

  • gone:"http,body",Body注入,根据contentType将HTTP正文解析为一个结构体,支持json、xml、form-data、x-www-form-urlencoded 等 contentType,要求被注入的结构体属性的数据类型为结构体或者结构体指针
  • gone:"http,query",Query注入,被注入的结构体属性的数据类型可以为结构体结构体指针字符串Number(int、uint、float64 …)字符串或Number的Slice
  • gone:"http,param",Url参数注入,将注入路由上定义的参数;要求被注入的结构体属性的数据类型为字符串Number类型

下面对Query注入,句几个例子:

type Q struct {
    Page int `form:"page"` //使用form标签指定参数名为page,默认是属性名Page
    PageSize int `form:"pageSize"`//使用form标签指定参数名为pageSize,默认是属性名PageSize
}

func handle(in struct{
    page int `gone:"http,query"` //未指定query参数名,去属性名为key
    thePage int `gone:"http,query=page"`//指定query参数名为page
    size int64 `gone:"http,query=pageSize` //指定query参数名为pageSize

    q *Q `gone:"http,query"` //被注入类型为一个结构体
    keywords []string `gone:"http,query=keywords"` //使用数组结构,允许Query参数出现多次
    oneKeyword string `gone:"http,query=keywords"` //不使用数组,只获取Query中的第一个keyword
}){
    //todo
}

假设某个请求的Query为:?page=10&pageSize=20&keywords=today&keywords=weather,使用上面handle处理请求,参数in的值如下:

  • in.page = 10
  • in.thePage = 10
  • in.size = 20
  • in.q = {Page = 10, PageSize = 20}
  • in.keywords = [today, weather]
  • in.oneKeyword = today

另外,处理函数还支持注入一些特殊结构体或指针(推荐使用指针):

  • gone.Content 请求上下文
  • http.Request Http请求
  • http.Header 请求头
  • url.Url url

框架还支持更多的注入标签和类型,请参考文档http 注入说明

请求处理函数参数

请求处理函数返回参数可以为如下几种形式:

  1. 不返回参数
  2. 返回一个非error的参数
  3. 返回数据和error

关于错误处理,更多可以参考:官方文档-错误处理

求赞助

如果觉得还可以,请帮忙在github上点个 ⭐️吧:
github地址:https://github.com/gone-io/gone

福利🔥添加交流群,赠送 Golang 多套 学习资料,夯实基础👍🏻👍🏻

上一篇:Gone框架介绍16 - 自动生成Priest
下一篇:Gone框架介绍18 - redis 分布式缓存 和 分布式锁

  • 32
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
去除访问德语网站上最常见的Binnen-Is品种。 Diese kleine Erweiterung成员Zumeck der besseren Lesbarkeit和Binnen的联系方式由Webseiten heraus完成。本能(德国)杂志,《性别之歌》(Gendergerechtigkeit)。在奥古斯·曼彻斯特的书店里,任何人都应该去找他,而祖德姆·辛德·塞特·尼古拉·泰勒·德·奥西弗勒·德·里奇·施泰因博格。辛格·冯·恩特法赫(KerineBenutzeroberfläche)的儿子戴维(Don Erweiterung)先生(Hon gar keineBenutzerInnenoberfläche) Mine einem Vorher-Nachher-Vergleich auf folgender Seite kann kontrolliert werden,ob allesordnungsgemäßfunktioniert:http://derstandard.at/1237228816647 NEU:Die Erweiterung帽子修女eineBenutzeroberfläche以einer Einstellungsseite的形式出现! ÜberdiesekönnenWebseiten festgelegt werden,德国von der Filterung律师事务所sollen oder dass Binnen-Is nur auf最好的Seiten律师事务所werden ---------------------------- 2.5-Behebt einen Fehler,黑名单/白名单域keine Auswirkungen auf dynamisch nachladende Seiteninhalte hatten-Filterverbesserungen 2.3.4-Bedarf的过滤器:Wen dieer Filtermodus in Einstellungen der Erweiterung aktiviert ist,wirdstandardmäßignicht gefiltert,aber ein Klick auf das Toolbar-Icon beregegeze imite jeweder an an -Icon angezeigt werden-Filterverbesserungen(verbesserte Erkennung von Doppelformen)2.3.4-Anpassung der Filter多种神经元Binnen-I Varianten-Optimierungfürschnellere Filterungbzw kürzereLadezeiten 2.3.3-Zus​​ammenhang mit Eingabefeldern中的Fehlerbehebung-Verbesserung des Filteralgorithmus(“ einem * rSchüler* In” wird nun erkannt)2.3.2-Toolbar-Iconfürdunkle Themes-Fehlerbehehangung 2. 3.1 “ Der * dieTäter* in”-Bessere Ausnahmen(安装,插入,指示,内联)-Feslerbehebung in Zusammenhang mit Eingabefeldern 2.3.0-Optimierungen bei Einstellungsseite-Chrome和Firefox版本和版本2.2.8-Die Filter überdas Toolbar-Icon aktiviert / deaktiviert werden 2.2.7-Filterung auch bei dynamisch nachgeladenen Inhalten(zB Twitter-Feed)-Filterung der Form“ jede / -r” 2.2.5-Binnen-Is nach dem Schema“Schüler.innen” werden nun erkannt-Verbesserte Erkennung von Doppelformen-Binnen-Is nach dem模式“Schüler/ inne / n” werden nun erkannt 2.1.3-选项zur Ersetzung von Partizip- Passivkonstruktionen(zB“ Studierende”)(Beta版本) 2.1.1-选项zur Deaktivierung der Filterung a

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dapeng-大鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值