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, obj, 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)
			}
		}
	}()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM