go-admin線上開發平臺學習-3[細節解析]

happlyfox發表於2021-02-18

本章節主要的內容是對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)
			}
		}
	}()

相關文章