go-admin在线开发平台学习-3[细节解析]

本章节主要的内容是对go-admin中的一些有趣编码进行分析,为自己以后提供一些借鉴

使用cli方式启动项目

使用cobra[眼镜蛇]完成强壮cli的工具,确保稳定。

使用cli的方式启动项目的好处显而易见,可以在进行配置的自定义化,而不是固定的使用某个配置文件中的信息。在一些需要频繁更换命令参数的场景下尤为有效。

cobra的使用有一个默认的规定,即新建一个cmd文件夹,基于这个文件夹定义自己的命令结构

1、小型项目

cmd 文件夹

-- root.go 根命令

-- version.go 版本命令【子命令】

2、中/大型项目

cmd 文件夹

--version 文件夹

​ --server.go

--config 文件夹

​ --server.go

-- root.go 入口指令

不同的项目选用不同的方式进行命令的定义。

监听中断信号

// 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间)
quit := make(chan os.Signal)
signal.Notify(quit,os.Interrupt)
<-quit
fmt.Printf("%s Shutdown Server ... \r\n",tools.GetCurrentTimeStr())

if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server Shutdown:",err)
}
log.Info("Server exiting")

信号监听,当遇到ctrl+c的时候当前服务结束,打印结束日志

配置文件Viper的使用

viper的使用,配置文件路径,获取viper根类

//数据库配置
cfgDatabase = viper.Sub("settings.database")
DatabaseConfig = InitDatabase(cfgDatabase)
//应用程序配置
cfgApplication = viper.Sub("settings.application")
ApplicationConfig = InitApplication(cfgApplication)

其他的内容与此方式类似

viper.Sub获取对应分类的内容,然后使用自定义的Init***函数初使化类

/tools/config文件夹中定义实体类,对应config.yml中的分类

举例:application.go对应图二的application分类内容,其他的也是同样意思

image-20210218155728868

image-20210218155808880

此目录下的内容,package包名为config。config下的配置信息使用大写表示【对外暴露】。如果其他地方要调用,引用包后使用config.分类名称.参数

即可得到配置文件的内容

初始化数据库

配置文件 dirver:mysql,定义不同的数据库字符串,程序启动时case 连接字符串,对不同的数据库类型做不同的配置

数据库日志开关作为单独配置区分,如果开启,数据库日志单独启用

现在程序的数据库.go都需要实现接口如下

type Database interface {
	Setup()
	Open(conn string,cfg *gorm.Config) (db *gorm.DB,err error)
	GetConnect() string
	GetDriver() string
}

image-20210218161101421

interface定义接口,其他的go文件实现接口-使用不同的开源数据库驱动

接口访问控制

casbin

轻量级开源访问控制框架,采用了元模型的设计思想,支持多种经典的访问控制方案,如基于角色的访问控制 RBAC、基于属性的访问控制 ABAC 等

策略文件

// Initialize the model from a string.
var text = `
[request_definition]
r = sub,obj,act

[policy_definition]
p = sub,act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && (keyMatch2(r.obj,p.obj) || keyMatch(r.obj,p.obj)) && (r.act == p.act || p.act == "*")
`

使用 github.com/casbin/gorm-adapter/v3作为casbin的数据库适配器即可

数据库上下文集成gin

gin一次请求共用一个数据库实例

image-20210218162726796

image-20210218162715014

r.Use()是gin的中间件扩展方法,WithContextDb方法说明的是,如果每次请求到来会打开一次数据库链接,获得数据库链接实例,将实例返回后作为参数传递给方法。如果有此实例,c.Set()方法执行,将此实例保存到gin执行上下文中。

全局异常处理

使用一个异常捕获方法recover()补获未知晓的异常

如果异常消息符合定义的规则,打印后返回给前台。

如果无异常,正常执行下一个定义的中间件

r.Use(CustomError)
func CustomError(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {

			if c.IsAborted() {
				c.Status(200)
			}
			switch errStr := err.(type) {
			case string:
				p := strings.Split(errStr,"#")
				if len(p) == 3 && p[0] == "CustomError" {
					statusCode,e := strconv.Atoi(p[1])
					if e != nil {
						break
					}
					c.Status(statusCode)
					fmt.Println(
						time.Now().Format("2006-01-02 15:04:05"),"[ERROR]",c.Request.Method,c.Request.URL,statusCode,c.Request.RequestURI,c.ClientIP(),p[2],)
					c.JSON(http.StatusOK,gin.H{
						"code": statusCode,"msg":  p[2],})
				}
			default:
				panic(err)
			}
		}
	}()
	c.Next()
}

web服务运行区分ssl和正常

从配置文件中获取内容,定义addr

得到对应的web执行引擎,当前使用gin

启动一个协程,判断如果ssl,使用TlS方法。否则使用正常模式

	srv := &http.Server{
		Addr:    config.ApplicationConfig.Host + ":" + config.ApplicationConfig.Port,Handler: global.Cfg.GetEngine(),}

	go func() {
		// 服务连接
		if config.SslConfig.Enable {
			if err := srv.ListenAndServeTLS(config.SslConfig.Pem,config.SslConfig.KeyStr); err != nil && err != http.ErrServerClosed {
				log.Fatal("listen: ",err)
			}
		} else {
			if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
				log.Fatal("listen: ",err)
			}
		}
	}()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Golang的文档和社区资源:为什么它可以帮助开发人员快速上手?
Golang:AI 开发者的实用工具
Golang的标准库:为什么它可以大幅度提高开发效率?
Golang的部署和运维:如何将应用程序部署到生产环境中?
高性能AI开发:Golang的优势所在
本篇文章和大家了解一下go语言开发优雅得关闭协程的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。1.简介本文将介绍首先为什么需要主...
这篇文章主要介绍了Go关闭goroutine协程的方法,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。1.简介本文将介绍首先为什么需要主动关闭gor...
本篇文章和大家了解一下go关闭GracefulShutdown服务的几种方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。目录Shutdown方法Regi...
这篇文章主要介绍了Go语言如何实现LRU算法的核心思想和实现过程,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。GO实现Redis的LRU例子常
今天小编给大家分享的是Go简单实现多租户数据库隔离的方法,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会...
这篇“Linux系统中怎么安装NSQ的Go语言客户端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希
本文小编为大家详细介绍“怎么在Go语言中实现锁机制”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么在Go语言中实现锁机制”文章能帮助大家解决疑惑,下面...
今天小编给大家分享一下Go语言中interface类型怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考
这篇文章主要介绍“怎么以正确的方式替换Go语言程序自身”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希
本文小编为大家详细介绍“Go语言中除法运算的效率怎么提高”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go语言中除法运算的效率怎么提高”文章能帮助大家解...
本文小编为大家详细介绍“Go语言中的next()方法怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go语言中的next()方法怎么使用”文章能帮助大家解决疑...
这篇文章主要介绍了Go语言中slice的反转方法怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Go语言中slice的反转方法怎...
这篇文章主要介绍“怎么使用Go语言实现数据转发功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用Go语
这篇文章主要讲解了“Go语言中怎么实现代码跳转”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究
这篇文章主要讲解了“Go语言如何多开协程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go语言如何多开协...