一、Gin框架简介
官网:https://gin-gonic.com/zh-cn/docs/
Gin 是一个用 Go (Golang) 编写的 HTTP web 框架。 它是一个类似于 martini 但拥有更好性能的 API 框架, 优于 httprouter,速度提高了近 40 倍。如果你需要极好的性能,使用 Gin 吧。
二、项目结构
gin
项目结构如下:
三、增加系统配置
我们系统配置使用yaml
文件,增加处理yaml
文件的包
go get -u gopkg.in/yaml.v2
在config
文件下增加config.yml
文件,内容如下:
# 相关配置
server:
model: debug
# 端口
part: :8888
# banner 配置
banner:
# banner 文件的名字
name: banner.txt
# 是否加载
loading: true
# 数据库相关配置
data:
# 数据类型
category: mysql
# 表前缀
prefix: tw_
# 数据库名称
database: tw_test
# 链接
ip: xx.xx.xxx.x
# 端口
part: 3306
# 用户名
username: root
# 密码
password: xxxxxxxxxxxxxxxx
# 打印sql
sql: true
# 初始化SQL配置
init:
name: init.sql
status: false
# 测试数据SQL配置
test:
name: test.sql
status: false
读取yml
文件
import (
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
)
// 定义Config结构体
type Config struct {
// 服务器相关配置
Server struct {
Part string `yml:"part"`
Model string `yml:"model"`
Banner struct {
Name string `yml:"name"`
Loading bool `yml:"loading"`
} `yml:"banner"`
} `yml:"server"`
// 数据库相关配置
Data struct {
Category string `yml:"category"`
Prefix string `yml:"prefix"`
DataBase string `yml:"database"`
Ip string `yml:"ip"`
Part string `yml:"part"`
Username string `yml:"username"`
Password string `yml:"password"`
Sql bool `yml:"sql"`
Init struct {
Name string `yml:"name"`
Status bool `yml:"status"`
} `yml:"init"`
Test struct {
Name string `yml:"name"`
Status bool `yml:"status"`
} `yml:"test"`
} `yml:"data"`
}
func NewConfig() *Config {
return &Config{}
}
// 读取配置映射到结构体
func (config *Config) ReadConfig() *Config {
file, err := ioutil.ReadFile("config/config.yml")
if err != nil {
log.Fatalln("读取文件config.yml发生错误")
return nil
}
if yaml.Unmarshal(file, config) != nil {
log.Fatalln("解析文件config.yml发生错误")
return nil
}
return config
}
四、数据源配置
官网:https://gorm.io/index.html
我们使用gorm
进行数据源配置,先添加gorm
和mysql
配置:
go get -u github.com/gin-gonic/gin
go get -u github.com/go-sql-driver/mysql
数据源配置文件,这里就是使用我们上面定义的Config
结构体数据:
import (
"fmt"
"gin-web/config"
"gin-web/model"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"log"
"time"
)
var Db *gorm.DB
var err error
// 数据库配置
func InitDb(config *Config) {
url := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
config.Data.Username,
config.Data.Password,
config.Data.Ip,
config.Data.Part,
config.Data.DataBase,
)
// 这个地方要注意,不要写称 := 写成 = 才对
Db, err = gorm.Open(config.Data.Category, url)
// 设置表前缀
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
return config.Data.Prefix + defaultTableName
}
if err != nil {
log.Fatalf("连接数据库【%s:%s/%s】失败, 失败的原因:【%s】", config.Data.Ip, config.Data.Part, config.Data.DataBase, err)
}
// db配置输出SQL语句
Db.LogMode(config.Data.Sql)
// 使用表名不适用复数
Db.SingularTable(true)
// 连接池配置
Db.DB().SetMaxOpenConns(20)
Db.DB().SetMaxIdleConns(10)
Db.DB().SetConnMaxLifetime(10 * time.Second)
// 判断是否需要用来映射结构体到到数据库
if config.Data.Init.Status {
Db.AutoMigrate(&entity.Article{})
}
log.Printf("连接数据库【%s:%s/%s】成功", config.Data.Ip, config.Data.Part, config.Data.DataBase)
}
五、启动Banner制作
官网:https://www.bootschool.net/ascii
读取Banner文件内容,其实就是简单的文件读取
func readBanner(name string) {
file, err := ioutil.ReadFile("config/" + name)
if err != nil {
log.Panicln("读取Banner文件失败")
}
fmt.Println(string(file))
}
六、创建Gin路由配置
我们在router
下面创建Router
文件,用来设置路由分组等一些配置
import (
"github.com/gin-gonic/gin"
)
// 初始化路由
func InitRouter(model string) *gin.Engine {
gin.SetMode(model)
r := gin.Default()
groupV1 := r.Group("api/v1")
// 文章相关的接口组
ArticleRouter(groupV1)
return r
}
将各个模块分开到不同的文件
import (
v1 "gin-web/api/v1"
"github.com/gin-gonic/gin"
)
func ArticleRouter(group *gin.RouterGroup) {
// 文章相关的接口
article := group.Group("/article")
{
// 获取文章列表
article.GET("/:id", v1.GetOneUser)
}
}
接着在api/v1/
下面增加控制器UserHandler
文件
import (
"gin-web/utils"
"github.com/gin-gonic/gin"
"net/http"
)
// 获取单个文件
func GetOneUser(c *gin.Context) {
var msg struct {
Name string `json:"user"`
Message string
Number int
Id string
}
param := c.Param("id")
msg.Name = "Lena"
msg.Message = "hey"
msg.Number = 123
msg.Id = param
c.JSON(http.StatusOK, utils.NewMsg().Success(msg))
}
七、返回数据封装
我们在上面可以看到,最后返回数据使用utils.NewMsg().Success(msg)
,这里我们使用一个消息结构体,对返回的数据进行封装。
const (
SUCCESS string = "001001200"
FAILED string = "001001400"
)
var CodeMsg = map[string]string{
SUCCESS: "操作成功",
FAILED: "操作失败",
}
// 消息实体
type ApiMsg struct {
// code
Code string `json:"code"`
// msg
Msg string `json:"msg"`
// data
Data interface{} `json:"data"`
}
func NewMsg() *ApiMsg {
return new(ApiMsg)
}
// 成功
func (this *ApiMsg) Success(data interface{}) *ApiMsg {
this.Code = SUCCESS
this.Msg = CodeMsg[SUCCESS]
this.Data = data
return this
}
// 失败
func (this *ApiMsg) Failed(msg string) *ApiMsg {
this.Code = FAILED
this.Msg = CodeMsg[FAILED]
return this
}
八、启动项目
上面的一堆设置,我们需要设置一个函数让他整合,在common
下新建Loading
文件
// 系统初始化加载的一些配置
func Loading() {
// No.1 读取系统配置
sysConfig := NewConfig().ReadConfig()
// No.2 加载Banner
readBanner(sysConfig.Server.Banner.Name)
// No.3 加载数据库连接
InitDb(sysConfig)
router.InitRouter(sysConfig.Server.Model).Run(sysConfig.Server.Part)
}
接着我们在main
中进行启动设置,这样入口文件就很简洁了!
import (
"fmt"
"gin-web/common"
)
func main() {
fmt.Println("Gin-Web,启动")
common.Loading()
}
启动之后的样子:
接着就是美滋滋的写我们的业务逻辑了!