「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战」
前言
上篇主要实践Gin框架ORM使用,做了一个简单的查询,但是还是有点瑕疵,把所有数据库配置写在了一个单文件中,没有容错处理,今天就这三个方向进行处理一下,暂时没想好项目项目架构,只好把大部分内容暂时都写在一个单文件,因为只有一个接口,并且把它使用Docker运行起来。
优化配置文件
在项目根目录新建一个config.ini文件,输入以下我觉得必要的内容:
[server]
# debug 开发模式,release 生产模式
AppMode = release
HttpPort = :8080
[database]
Db = mysql
DbHost = ***.***.***.***
DbPort = 3306
DbUser = *****
DbPassWord = *********
DbName = ********
优化框架报错
为了前端更好的处理接口的内容,处理相关报错,统一下接口规范,内容有点多,新建一个文件夹global,再该文件夹新建一个golab.go,输入以下内容:
package global
import (
"net/http"
"github.com/gin-gonic/gin"
)
//Result 暴露
type Result struct {
Ctx *gin.Context
}
//ResultCont 返回的结果:
type ResultCont struct {
Code int `json:"code"` //提示代码
Msg string `json:"msg"` //提示信息
Data interface{} `json:"data"` //数据
}
//NewResult 创建新返回对象
func NewResult(ctx *gin.Context) *Result {
return &Result{Ctx: ctx}
}
//Success 成功
func (r *Result) Success(data interface{}) {
if data == nil {
data = gin.H{}
}
res := ResultCont{}
res.Code = 200
res.Data = data
res.Msg = "成功!"
r.Ctx.JSON(http.StatusOK, res)
}
//Error 出错
func (r *Result) Error(code int, msg string, data interface{}) {
if data == nil {
data = gin.H{}
}
res := ResultCont{}
res.Code = code
res.Msg = msg
res.Data = data
r.Ctx.JSON(http.StatusOK, res)
}
其他优化
在启动文件新增了环境变量的读取,接口规范化:
package main
import (
"fmt"
"main/global"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"gopkg.in/ini.v1"
)
var db *gorm.DB
var HttpPort string
var AppMode string
type UrlType struct {
ID uint `gorm:"primary_key"`
Name string
UrlLists []UrlList `gorm:"FOREIGNKEY:TypeID;ASSOCIATION_FOREIGNKEY:ID"`
}
type UrlList struct {
ID uint `gorm:"primary_key"`
TypeID uint // 默认外键, 用户Id
Name string
URL string
}
type config struct {
App string
}
func init() {
//配置文件路径
file, err := ini.Load("config.ini")
if err != nil {
fmt.Println("配置文件读取错误,请检查文件路径:", err)
}
//读取项目运行配置
HttpPort = file.Section("server").Key("HttpPort").String()
AppMode = file.Section("server").Key("AppMode").String()
//读取数据配置
DBUser := file.Section("database").Key("DbUser").String()
Password := file.Section("database").Key("DbPassWord").String()
Host := file.Section("database").Key("DbHost").String()
Port := file.Section("database").Key("DbPort").MustInt(3306)
Db := file.Section("database").Key("DbName").String()
connArgs := fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", DBUser, Password, Host, Port, Db)
//创建一个数据库的连接
db, err = gorm.Open("mysql", connArgs)
if err != nil {
panic(err)
}
db.SingularTable(true) //去掉数据库自动迁移数据名加的s
db.AutoMigrate(&UrlList{}, &UrlType{}) //自动迁移
}
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
defer db.Close()
r.GET("/index", func(c *gin.Context) {
var list []UrlType
db.Debug().Preload("UrlLists").Find(&list)
result := global.NewResult(c)
result.Success(list)
})
gin.SetMode(AppMode)
r.Run(HttpPort)
}
现在看看接口返回的内容:
非常的规范化了,成功的接口有code,msg,data三大部分
DockerFile编写
DockerFile目的就是把项目打包起来,方便项目部署,golang是一个编译型的语言,我们看可以采用多段编译优化镜像大小,先编译使用一个基础镜像,再把编译打包出来的二进制文件,放到另外一个镜像运行打包发布。
在项目根目录新建一个文件名为:Dockerfile,注意暴露的端口号,输入以下内容:
##
# ---------- building ----------
##
#编译用这个镜像
FROM golang:alpine AS builder
#设置工作路径
WORKDIR /build
#把项目所有文件复制到镜像的根目录文件夹中
ADD . ./
# 设置Go语言的环境变量,打开Go Module模式。设置包下载源,有利于快速下载包
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn
#下载go.mod里面的包
RUN go mod download
#编译成二进制文件
RUN go build -o my_gin_web .
##
# ---------- run ----------
##
#换一个镜像
FROM alpine:latest
#采用相同的工作目录
WORKDIR /build/
#把编译好的文件复制到到运行镜像的目录下
COPY --from=builder /build .
#打开端口
EXPOSE 8080
#运行二进制文件
ENTRYPOINT ["./my_gin_web"]
然后打包镜像:
docker build -t my_gin_web:v1 .
运行容器:
docker run -d --name my_gin_web -p 8080:8080 my_gin_web:v1
在docker 客户端就可以看到运行完成:
接口也正常:
总结
今天稍微了优化了Gin框架细节,制作gin镜像,运行容器,下篇准备部署线上环境,做一下相关CI脚本。