从零开始摸索VUE,配合Golang搭建导航网站(十.Gin框架优化,DockerFile编写)

869 阅读3分钟

「这是我参与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)
}

现在看看接口返回的内容:

image.png 非常的规范化了,成功的接口有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 客户端就可以看到运行完成:

image.png 接口也正常: image.png

总结

今天稍微了优化了Gin框架细节,制作gin镜像,运行容器,下篇准备部署线上环境,做一下相关CI脚本。