内容简介:我们所说的公共类包,包括 dbutil、util、common 这三个包,下面展开一一说明它们里面关键的函数。**dbutil**顾名思义就是数据库工具类,我们采用了第三方 sqlx 类包来操作数据库, sqlx 的 DB 对象在 dbutil 里完成初始化工作,我们把这个简单的功能独立到一个包里,是为了以后遇到新的需求,易于扩展。比如 sqlx 有更换成 gorp、gorm 等其他第三方数据库类包,或者新增 redis 数据库的可能,到时我们只需要在这个包里更改就好。涉及更改的代码地方会大大缩小。另外独立
我们所说的公共类包,包括 dbutil、util、common 这三个包,下面展开一一说明它们里面关键的函数。
**dbutil**顾名思义就是数据库 工具 类,我们采用了第三方 sqlx 类包来操作数据库, sqlx 的 DB 对象在 dbutil 里完成初始化工作,我们把这个简单的功能独立到一个包里,是为了以后遇到新的需求,易于扩展。比如 sqlx 有更换成 gorp、gorm 等其他第三方数据库类包,或者新增 redis 数据库的可能,到时我们只需要在这个包里更改就好。涉及更改的代码地方会大大缩小。另外独立成一个包,不限于 service 服务层的其他包也可以使用。
*代码清单 - sqlx DB 对象实例化实现*
<em>package dbutil
import (
"log"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"chapter01/src/common"
)
var (
// SQLXDB 声明一个 sqlx DB 实例对象
SQLXDB *sqlx.DB
)
func init() {
if SQLXDB != nil {
return
}
SQLXDB = NewSQLXDB()
}
// NewSQLXDB 实例化一个新的 sqlx DB 实例对象
func NewSQLXDB() *sqlx.DB {
configKit := common.ConfigKit
if configKit == nil {
return nil
}
dbDrivers, err := configKit.String("db-mysql", "db_drivers")
if err != nil {
log.Fatalf("无法获取配置文件的 db_drivers %#v", err)
}
dbConnection, err := configKit.String("db-mysql", "db_connection")
if err != nil {
log.Fatalf("无法获取配置文件的 db_connection %#v", err)
}
maxIdleConn, _ := configKit.Int("db-mysql", "db_max_idle_conn")
maxOpenConn, _ := configKit.Int("db-mysql", "db_max_open_conn")
connMaxLifetime, _ := configKit.Int("db-mysql", "db_conn_max_lifetime")
db, err := sqlx.Open(dbDrivers, dbConnection)
if err != nil {
log.Fatalf("sqlx 初始化数据库出错:\n %#v", err)
panic(err.Error())
}
db.SetMaxIdleConns(maxIdleConn)
db.SetMaxOpenConns(maxOpenConn)
db.SetConnMaxLifetime(time.Duration(connMaxLifetime) * time.Second)
return db
}</em>
包定义了一个全局变量 SQLXDB,包初始化的时候,检查 SQLXDB 为空,就进行初始化,初始化所需要的数据库信息,都是从配置文件 config.ini 获取的, 比如数据库 IP、用户名、密码等。
**util**包是独立于项目的类包,把它移植到其他项目照样是可以使用的。我们一般都是在项目开发过程中,不断积累此类的工具包,让这个工具包越来越完善,功能越来越强大。这个包一般存在一些 Go 内置函数的封装,或者第三方知名类包的封装。安装大业务分文件存放,比如字符串处理,文件处理,分页逻辑处理,http 处理,图片处理等等。由于 util 包涉及到的函数相当丰富,我们不能一一列举说明,我们只选择关键的函数说明一下。
*代码清单 - request 转 JSON 字符串*
// RequestJSON 直接获取 请求参数是 JSON 的字符串
func RequestJSON(req *http.Request) string {
if req != nil && req.Body != nil {
result, err := ioutil.ReadAll(req.Body)
if err == nil {
return string(result)
}
}
return ""
}
*代码清单 - 发送 POST 请求的函数*
<em>// SendHTTPPost 发起 HTTP POST 请求
func SendHTTPPost(url string, param string, mime string) string {
resp, err := http.Post(url, mime, strings.NewReader(param))
if err != nil {
return ""
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ""
}
return string(body)
}
// SendHTTPDo 发起 HTTP Do 详细请求
func SendHTTPDo(url string, method string, params string, mime string, header map[string]string, cookie string) string {
req, err := http.NewRequest(method, url, strings.NewReader(params))
if err != nil {
return ""
}
req.Header.Set("Content-Type", mime)
req.Header.Set("Cookie", cookie)
if header != nil && len(header) > 0 {
for k, v := range header {
req.Header.Set(k, v)
}
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ""
}
return string(body)
}</em>
*代码清单 - 文件转换 []byte 字节数组,[]byte 保存*
<em>// ReadFileToBytes 小文件推荐一次性读取,这样程序更简单,而且速度最快。
func ReadFileToBytes(filePath string) []byte {
byt, err := ReadFile(filePath)
if err != nil {
log.Println(err)
return nil
}
return byt
}
// BytesToFile 把字节数组转成文件
func BytesToFile(byt []byte, filename string) error {
//如果文件夹不存在,则新建文件夹
CheckCreatePath(GetFilePath(filename))
return ioutil.WriteFile(filename, byt, 0777)
}</em>
*代码清单 - 图片压缩缩放剪切*
<em>// ImageResize 指定宽高比例缩放图片
func ImageResize(srcFileName string, width, height int, targetFileName string) {
// Open the test image.
src, err := imaging.Open(srcFileName)
if err != nil {
log.Fatalf("Open failed: %v", err)
}
// Resize the cropped image to width = 256px preserving the aspect ratio.
dst := imaging.Resize(src, 0, height, imaging.Lanczos)
// Save the resulting image using JPEG format.
err = imaging.Save(dst, targetFileName)
if err != nil {
log.Fatalf("Save failed: %v", err)
}
}
// ImageCut 指定宽高剪切图片
func ImageCut(srcFileName string, width, height int, targetFileName string) {
// Open the test image.
src, err := imaging.Open(srcFileName)
if err != nil {
log.Fatalf("Open failed: %v", err)
}
// Resize the cropped image to width = 256px preserving the aspect ratio.
dst := imaging.Fill(src, width, height, imaging.Center, imaging.Lanczos)
// Save the resulting image using JPEG format.
err = imaging.Save(dst, targetFileName)
if err != nil {
log.Fatalf("Save failed: %v", err)
}
}</em>
*代码清单 - 多数据分页类*
<em>// Paginate 分页结构体
type Paginate struct {
Start uint64 // 开始索引 从1开始
End uint64 // 结束索引 包括自身
RowsCount uint64 // 总行数
}
// NewPaginate 实例化一个 Paginate 结构体
func NewPaginate(start, end uint64) *Paginate {
if start >= end {
start = 1
end = 10
}
p := &Paginate{
Start: start,
End: end,
RowsCount: 0,
}
return p
}
// GetPageIndex 获取当前页索引
func (p *Paginate) GetPageIndex() uint64 {
return p.Start - 1
}
// GetPageSize 获取每页记录数
func (p *Paginate) GetPageSize() uint64 {
return p.End - p.Start + 1
}
// GetTotalPage 获取总页数
func (p *Paginate) GetTotalPage() uint64 {
if p.RowsCount > 0 {
var t uint64
if p.RowsCount%uint64(p.GetPageSize()) > 0 {
t = 1
}
return uint64(p.RowsCount/uint64(p.GetPageSize()) + t)
}
return p.RowsCount
}
// GetPageCount 根据记录总数和页数尺寸,获取总页数;外部方法
func GetPageCount(rowsCount uint64, pageSize uint64) (pageCount uint64) {
if rowsCount <= 0 || pageSize <= 0 {
return 0
}
pageCount = rowsCount / pageSize
pageRemainder := rowsCount % pageSize
if pageCount <= 0 {
return 1
}
if pageRemainder > 0 {
return pageCount + 1
}
return pageCount
}</em>
分页类,传入 start 和 end 开始索引和结束索引,得到 offset 和 limit。
*代码清单 - render 的初始化*
<em>var (
r *render.Render
renderUtil *RenderUtil
)
// NewRender 实例化一个渲染类结构体
func NewRender(debug bool, templateDir string) *RenderUtil {
renderUtil = &RenderUtil{
debug: debug,
templateDir: templateDir,
}
return renderUtil
}
// ClassicRender 实例化一个渲染类结构体
func ClassicRender() *RenderUtil {
return NewRender(false, "template")
}
// RenderUtil 渲染类结构体
type RenderUtil struct {
debug bool
templateDir string
}
// InitRender 初始化一个 render.Render 实例
func (renderUtil *RenderUtil) InitRender() *render.Render {
if r == nil {
r = render.New(render.Options{
Directory: renderUtil.templateDir,
Layout: "",
Extensions: []string{".html", ".tmpl"},
Funcs: []template.FuncMap{AppHelpers},
Delims: render.Delims{Left: "{{", Right: "}}"},
Charset: charsetDefault,
IndentJSON: renderUtil.debug,
IndentXML: renderUtil.debug,
PrefixJSON: []byte(""),
PrefixXML: []byte(""),
HTMLContentType: "text/html",
IsDevelopment: renderUtil.debug,
UnEscapeHTML: true,
StreamingJSON: true,
RequirePartials: true,
DisableHTTPErrorRendering: !renderUtil.debug,
})
}
return r
}</em>
依赖 render 第三方类包,我们可以在 controller 控制层方便的输出 HTML,JSON,Text,XML 类型数据给终端。
**common**公共工具类包,和业务紧密关联,比如一些配置文件读取,错误打印,返回码和错误常量等。这些东西迁移到其他项目,可能就用不上了。以下是一些比较重要的代码。
*代码清单 - 配置文件工具类*
const (
configPathDefault = "config.ini"
)
var (
//ConfigKit 配置文件工具
ConfigKit *config.Config
)
func init() {
LoadConfigure()
}
// LoadConfigure 加载获取配置文件
func LoadConfigure() {
if ConfigKit == nil {
var err error
ConfigKit, err = config.ReadDefault(configPathDefault)
if err != nil {
FatalErr("获取配置文件 config.ini 失败", err.Error())
}
}
}
//GetConfString 获取配置文件的某个字符串配置属性
func GetConfString(section, option string) string {
v, err := ConfigKit.String(section, option)
if err != nil {
ShowErr(err)
return ""
}
return v
}
//GetConfInt 获取配置文件的某个数值配置属性
func GetConfInt(section, option string) int {
v, err := ConfigKit.Int(section, option)
if err != nil {
ShowErr(err)
return 0
}
return v
}
// GetConfBool 获取配置文件的某个布朗配置属性
func GetConfBool(section, option string) bool {
v, err := ConfigKit.Bool(section, option)
if err != nil {
ShowErr(err)
return false
}
return v
}
*代码清单 - 错误打印类*
<em>func init() {
logrus.SetFormatter(&logrus.TextFormatter{})
logrus.SetReportCaller(true)
debug := GetConfBool("default", "dev_mode")
if debug {
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.SetLevel(logrus.DebugLevel)
}
}
// FatalErr 打印致命错误,程序终止
func FatalErr(args ...interface{}) {
if len(args) > 0 {
logrus.Fatal(args)
}
}
// ShowErr 打印严重错误
func ShowErr(args ...interface{}) {
if len(args) > 0 {
logrus.Error(args)
}
}
// ShowDebug 打印 Debug 信息
func ShowDebug(args ...interface{}) {
if len(args) > 0 {
logrus.Debug(args)
}
}
// ShowInfo 打印信息
func ShowInfo(args ...interface{}) {
if len(args) > 0 {
logrus.Info(args)
}
}</em>
*代码清单 - 错误码和错误信息*
<em>const (
// CodeSuccess 成功 code key
CodeSuccess = 1
// CodeFailure code key
CodeFailure = 0
// Code1000 code key
Code1000 = 1000
// Code1001 code key
Code1001 = 1001
// Code1002 code key
Code1002 = 1002
// Code1003 code key
Code1003 = 1003
// Code1004 code key
Code1004 = 1004
// Code1005 code key 仅支持POST请求!
Code1005 = 1005
// MsgEmpty 空字符串
MsgEmpty = ""
// MsgFailure 操作失败!
MsgFailure = "操作失败!"
// Msg1001 程序內部异常!
Msg1001 = "程序內部异常!"
// Msg1002 数据库异常!
Msg1002 = "数据库异常!"
// Msg1003 缺少参数!
Msg1003 = "缺少参数!"
// Msg1004 参数格式有误!
Msg1004 = "参数格式有误!"
// Msg1005 仅支持POST请求!
Msg1005 = "仅支持POST请求!"
)
var (
// CodeMsgMap map code and msg
CodeMsgMap = map[int]string{
CodeSuccess: MsgEmpty,
CodeFailure: MsgFailure,
Code1001: Msg1001,
Code1002: Msg1002,
Code1003: Msg1003,
Code1004: Msg1004,
Code1005: Msg1005,
}
)</em>
小结
本章节主要罗列一些关键的函数代码,关键的函数,需要项目不断的沉淀和优化完善,因为它们都是抽象出来的公共对象,很多地方引用到,特别是 util 包的函数。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Java8 函数接口
- java8的函数式接口
- 深入理解 lambda表达式 与 函数式编程 函数式接口源码解析(二)
- Go指南-谈谈Go的接口与函数
- Java8新特性学习-函数式接口
- 用 Go 开发接口服务--灵活写 Dao 数据层函数
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Docker——容器与容器云
浙江大学SEL实验室 / 人民邮电出版社 / 2015-9-1 / 89.00元
本书从实践者的角度,在讲解Docker高级实践技巧的同时,深入到源代码层次,为读者梳理出Docker容器技术和基于Docker的容器云技术(如Kubernetes)的实现方法和设计思路,帮助读者理解如何在实际场景中利用Docker解决问题并启发新的思考。全书包括两部分,第一部分深入解读Docker容器技术,包括Docker入门、架构总览、Docker容器核心原理解读,以及Docker高级实践技巧;......一起来看看 《Docker——容器与容器云》 这本书的介绍吧!