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
    • 安装gone辅助工具
    • 使用gone命令创建项目
    • 编译并运行
    • 测试接口
    • 项目简单介绍
      • 目录结构
      • 项目特点
      • 部分代码讲解
      • HTTP 注入
      • 请求处理函数参数

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 等 contentTypereq *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,默认是属性名PagePageSize int `form:"pageSize"`//使用form标签指定参数名为pageSize,默认是属性名PageSize
}func handle(in struct{page int `gone:"http,query"` //未指定query参数名,去属性名为keythePage int `gone:"http,query=page"`//指定query参数名为pagesize int64 `gone:"http,query=pageSize` //指定query参数名为pageSizeq *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

上一篇:Gone框架介绍16 - 自动生成Priest

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/327289.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频汇聚管理/安防监控系统EasyCVR如何开启和调用验证码登录接口?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。视频汇聚融合管理平台EasyCVR既具备传统安防视…

C语言写扫雷游戏(数组和函数实践)

目录 最后是代码啦! 手把手教你用C语言写一个扫雷游戏! 1.我们搭建一下这个多文件形式的扫雷游戏文件结构 2.在主函数里面设置一个包含游戏框架的菜单 菜单可以方便游戏玩家选择要进行的动作和不断地进行下一局。 3.switch语句连接不同的结果 菜单可…

AI与边缘设备,光子芯片,AI规划能力,自然语言驱动的AI游戏

1 Archetype AI 发布了一个创新的人工智能平台 —— Newton 这是一个专门为理解物理世界设计的基础模型。 Newton 设计用于连接实时物理数据,其数据源是全球数十亿传感器的输入,实现了对物理现实的直接解读。 利用从各种传感器(如加速度计…

被动防护不如主动出击

自网络的诞生以来,攻击威胁事件不断涌现,网络攻防对抗已然成为信息时代背景下的一场无硝烟的战争。然而,传统的网络防御技术,如防火墙和入侵检测技术,往往局限于一种被动的敌暗我明的防御模式,面对攻击者无…

Windows Qt中支持heic 图片显示

安装vcpkg: git clone https://github.com/microsoft/vcpkg 执行脚本: .\vcpkg\bootstrap-vcpkg.bat 在安装之前如果需要指定vs的编译器, 在如下文件中做更改, 我指定的是用vs2019编译的: D:\vcpkg\vcpkg\triplets 增…

android图标底色问题,debug与release不一致

背景 在android 8(sdk 26)之前的版本,直接使用图片文件作为图标,开发时比较容易控制图标,但是不同的安卓定制版本就不容易统一图标风格了。 在android 8及之后的版本,图标对应的是ic_launcher.xml&#x…

VC 编程开发中的 封装类 :log日志类 和SQL server 操作类 源代码

VC 编程开发中的 封装类 :日志类 和SQL server 操作类 源代码 在VC(Visual C)开发中,日志文件输出是一个至关重要的环节,它对于程序调试、问题排查以及系统监控等方面都具有不可替代的作用。以下是对日志文件输出在VC开…

网站localhost和127.0.0.1可以访问,本地ip不可访问解决方案

部署了一个网站, 使用localhost和127.0.0.1加端口号可以访问, 但是使用本机的ip地址加端口号却不行. 原因可能有多种. 可能的原因: 1 首先要确认是否localhost对应的端口是通的(直接网址访问), 以及你无法访问的那个本机ip是否正确(使用ping测试); 2 检查本机的防火…

好题总结汇总

好题总结汇总 总结一些做完很有收获的题。 一、经典问题 DP的结合 1、题意: 给定 n n n 种颜色的球的数量 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1​,a2​,...,an​,选出一些不同种类的球(也就是在n种球中选球的任意情况),将球…

企业如何通过云服务器实现全球连通运营

如果说互联网是一座桥,连接起了全球各地的信息,那云服务器就如同一座高速公路,帮助企业轻松实现跨国家、跨时区的全球运营。 这个听起来像科幻电影的情节其实已经成为了我们现实生活的一部分。现在就来具体看一下如何做到这一点吧。 其一&…

【Linux】Linux——Centos7安装

【Linux】Linux——Centos7安装 新建虚拟机 选择自定义安装下一步 硬件兼容性使用默认最高即可,下一步 选择稍后安装操作系统,下一步 选择客户机操作系统为 Linux ,并选择下方版本为所安装 Linux 镜像同版本,下一步 虚拟机名称与…

idea-自我常见配置

1. 主题配置 2. 显示方法分隔符 Editor->General->Appearance 3. 忽略大小写提示 Editor->General->Code Completion 4. 自动导包 Editor->general->Auto Import 5. 取消单行显示Tabs Editor->General->Editor Tabs 效果如下图: 6. 设置…

idea启动Jsp非maven项目时的一些步骤

文章目录 事前准备eclipse项目举例idea打开eclipse项目安装tomcat配置启动项启动测试 一些小问题到不到servlet 事前准备 非社区版idea【否则启动项无法配置】tomcatmysql eclipse项目举例 idea打开eclipse项目 剩下的全部下一步即可 安装tomcat 自己的文章 Javaweb - t…

OpenAI GPT-4

本文翻译整理自:https://openai.com/index/gpt-4-research/ (March 14, 2023) 文章目录 一、关于 GPT-4二、能力视觉输入Visual inputs: chart reasoningSample 2 of 7 操纵性Steerability: Socratic tutorSample 1 of 3 三、局限性四、风险与缓解措施五、训练流程…

caj文件是什么?caj是什么文件?考研学生赶紧收藏!

在学术研究的广阔领域中,尤其是对于那些致力于深入研究、不断拓宽知识边界的考研学子们来说,了解并掌握各种学术资源的获取与利用方法显得尤为重要。其中,CAJ文件作为一种常见的学术文件格式,其重要性和使用频率不容忽视。那么&am…

软件设计师笔记(三)-设计模式和算法设计

本文内容来自笔者学习zst 留下的笔记,都是零碎的要点,查缺补漏,希望大家都能通过,记得加上免费的关注!谢谢!本章主要以下午题出现形式为主! 文章编辑于:2024-5-13 13:43:47 目录 1…

Midjourney Imagine API 申请及使用

Midjourney Imagine API 申请及使用 申请流程 要使用 Midjourney Imagine API,首先可以到 Midjourney Imagine API 页面点击「Acquire」按钮,获取请求所需要的凭证: 如果你尚未登录或注册,会自动跳转到登录页面邀请您来注册和登…

_remote.repositories作用

问题描述 明明我本地有某个依赖但是却还是报错,原因就是存在_remote.repositories且你的远程仓库中找不到该依赖,可能发生在你修改了远程仓库或镜像时。 例子 本地有这个依赖,但是报错。 解决 删除_remote.repositories文件&#xff0…

vue自定义权限指令

定义v-hasPermi指令 /*** v-hasPermi 操作权限处理*/import useUserStore from /store/modules/userexport default {mounted(el, binding, vnode) {const { value } bindingconst all_permission "*:*:*";const permissions useUserStore().permissions&#xff…

Netgear无线路由器漏洞复现(CVE-2019-20760)

漏洞概述 漏洞服务: uhttpd 漏洞类型: 远程命令执行 影响范围: 1.0.4.26之前的NETGEAR R9000设备会受到身份验证绕过的影响 解决建议: 更新版本 漏洞复现 操作环境: ubuntu:22.04 qemu-version: 8.1…