Go-Gin-Example 第八部分 优化配置接口+图片上传功能

前情提要

学习项目github地址

上一部分学习笔记

本节目标

  • 优化配置结构(因为配置项越来越多)
  • 抽离 原 loggingFile 便于公用(logging、upload 各保有一份并不合适)
  • 实现上传图片接口(需限制文件格式、大小)
  • 修改文章接口(需支持封面地址参数)
  • 增加 blog_article (文章)的数据库字段
  • 实现 http.FileServer

优化配置结构

讲解

在先前章节中,我们通过读取KEY的方式读取配置项(建立setting模块)
本次需求中,需要增加图片的配置项,总体就有些冗余了

我们采用以下解决方法:

  • 映射结构体:使用 MapTo 来设置配置参数
  • 配置统管:所有的配置项统管到 setting

落实

修改配置文件

修改 conf/app.ini

增加了 5 个配置项用于上传图片的功能,4文件日志方面的配置项

[app]
PageSize = 10
JwtSecret = 233

RuntimeRootPath = runtime/

ImagePrefixUrl = http://127.0.0.1:8000
ImageSavePath = upload/images/
# MB
ImageMaxSize = 5
ImageAllowExts = .jpg,.jpeg,.png

LogSavePath = logs/
LogSaveName = log
LogFileExt = log
TimeFormat = 20060102

[server]
#debug or release
RunMode = debug
HttpPort = 8000
ReadTimeout = 60
WriteTimeout = 60

[database]
Type = mysql
User = root
Password = rootroot
Host = 127.0.0.1:3306
Name = blog
TablePrefix = blog_

优化配置读取及设置初始化顺序

第一步

将散落在其他文件里的配置都删掉,统一在 setting 中处理以及修改 init 函数为 Setup 方法

  1. 打开 pkg/setting/setting.go 文件,修改如下:
package models

import (
	"fmt"
	"log"
	"time"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"

	"github.com/kingsill/gin-example/pkg/setting"
)

// 定义一个全局的数据库连接变量
var db *gorm.DB

// Model 设定常用结构体,可以作为匿名结构体嵌入到别的表格对应的结构体
type Model struct {
   
	ID         int `gorm:"primary_key" json:"id"`
	CreatedOn  int `json:"created_on"`
	ModifiedOn int `json:"modified_on"`
	DeletedOn  int `json:"deleted_on"`
}

func Setup() {
   
   //配置文件加载
   Cfg, err := ini.Load("conf/app.ini")
   if err != nil {
   
      log.Fatalf("Fail to parse 'conf/app.ini': %v", err)
   }

   //将app section 部分映射到AppSetting结构体上
   err = Cfg.Section("app").MapTo(AppSetting)
   if err != nil {
   
      log.Fatalf("Cfg.MapTo AppSetting err: %v", err)
   }
   //将图片最大大小设置从5字节Byte转换为5兆字节MB
   AppSetting.ImageMaxSize = AppSetting.ImageMaxSize * 1024 * 1024

   err = Cfg.Section("server").MapTo(ServerSetting)
   if err != nil {
   
      log.Fatalf("Cfg.MapTo ServerSetting err: %v", err)
   }

   //将读取时自动转换的类型转换为时间间隔了,只不过是最小单位纳秒
   ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.Second
   ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second

   err = Cfg.Section("database").MapTo(DatabaseSetting)
   if err != nil {
   
      log.Fatalf("Cfg.MapTo DatabaseSetting err: %v", err)
   }
}

在这里,我们做了如下几件事:

  • 编写与配置项保持一致的结构体(App、Server、Database
  • 使用 MapTo 将配置项映射到结构体上
  • 对一些需特殊设置的配置项进行再赋值
  1. 修改models.go
    init函数改为Setup方法,将独立读取的DB配置项删除,改为统一读取setting
package models

import (
...
)

// 定义一个全局的数据库连接变量
var db *gorm.DB

// Model 设定常用结构体,可以作为匿名结构体嵌入到别的表格对应的结构体
type Model struct {
   
	ID         int `gorm:"primary_key" json:"id"`
	CreatedOn  int `json:"created_on"`
	ModifiedOn int `json:"modified_on"`
	DeletedOn  int `json:"deleted_on"`
}

func Setup() {
   
	var err error

	//使用gorm框架初始化数据库连接
	db, err = gorm.Open(setting.DatabaseSetting.Type, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
		setting.DatabaseSetting.User,
		setting.DatabaseSetting.Password,
		setting.DatabaseSetting.Host,
		setting.DatabaseSetting.Name))

	if err != nil {
   
		log.Println(err)
	}

	//自定义默认表的表名,使用匿名函数,在原默认表名的前面加上配置文件中定义的前缀
	gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
   
		return setting.DatabaseSetting.TablePrefix + defaultTableName
	}

	//gorm默认使用复数映射,当前设置后即进行严格匹配
	db.SingularTable(true)
	//log记录打开
	db.LogMode(true)

	//进行连接池设置
	db.DB().SetMaxIdleConns(10)
	db.DB().SetMaxOpenConns(100)

	//替换Create和Update回调函数
	db.Callback().Create().Replace("gorm:update_time_stamp", updateTimeStampForCreateCallback)
	db.Callback().Update().Replace("gorm:update_time_stamp", updateTimeStampForUpdateCallback)

	//添加删除的回调CallBacks
	db.Callback().Delete().Replace("gorm:delete", deleteCallback)
}


// CloseDB 与数据库断开连接函数
func CloseDB() {
   
	defer db.Close()
}

// updateTimeStampForCreateCallback 在创建记录时设置 `CreatedOn`, `ModifiedOn`
func updateTimeStampForCreateCallback(scope *gorm.Scope) {
   
	...
}

// updateTimeStampForUpdateCallback 在更新记录时设置 `ModifyOn`
func updateTimeStampForUpdateCallback(scope *gorm.Scope) {
   
...
}

// 设定delete操作的callback逻辑
func deleteCallback(scope *gorm.Scope) {
   
	...
}

// 判断是否为空来进行空格插入,防止sql注入,保证安全性
func addExtraSpaceIfExist(str string) string {
   
	...
}

  1. 修改log.go
    init函数改为Setup方法
func Setup() {
   
	//获取log文件目录
	filePath := getLogFileFullPath()

	//得到log文件句柄
	F = openLogFile(filePath)

	//创建一个新的日志记录器
	logger = log.New(F, DefaultPrefix, log.LstdFlags)
}
  1. 修改pkg/logging/file.go

    独立的 LOG 配置项删除,改为统一读取 setting,修改这两个函数即可

// 返回log文件的前缀路径,算是一个具有仪式感的函数
func getLogFilePath() string {
   
	return fmt.Sprintf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值