本示例分为三部分组成:项目创建、基础框架、业务代码。本部分是基础框架的目录结构和代码编写。目录和文件包括main.go、config、数据库init、router等。
项目目录结构
main.go
项目执行入口文件(go run main.go),初始化各种配置(数据库、日志、路由数据等),使用第三方Gin包启动应用服务器。
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"gotest/config"
"gotest/model"
"gotest/router"
"log"
)
func main() {
fmt.Println("gotest - 初始化配置信息")
if err := config.Init();err != nil {
panic(err)
}
fmt.Println("gotest - 初始化MySql数据库对象")
if err := model.Init();err != nil {
panic(err)
}
// Set gin mode:DebugMode ReleaseMode TestMode
gin.SetMode(viper.GetString("gin_mode"))
// Create the Gin engine
gEngine := gin.New()
// 初始化路由
router.InitRouter(gEngine)
log.Printf("Start listening on http address: %s\n", viper.GetString("server_addr"))
// 启动服务器
if err := gEngine.Run(viper.GetString("server_addr"));err != nil {
log.Fatal("ListenAndServer is error:", err)
}
}
config.yaml
配置信息文件
mysql:
#最大允许连接数
max_open_conns: 10
#最大空闲连接数
max_idle_conns: 5
#链接
source_name: root:123456@tcp(127.0.0.1:3306)/gotest?parseTime=true&charset=utf8&loc=Local
# HTTP地址和端口
server_addr: :8081
# gin框架的三种模式:DebugMode ReleaseMode TestMode
gin_mode: "debug"
config.go
读取配置文件的程序,并初始化日志信息
package config
import (
"github.com/spf13/viper"
"log"
"os"
"time"
)
// Init 读取初始化配置文件
func Init() error {
// 初始化配置文件
if err := Config(); err != nil {
return err
}
// 初始化日志信息
LogInfo()
return nil
}
// Config viper解析配置文件
func Config() error {
viper.AddConfigPath("conf") // 路径
viper.SetConfigName("config") // 文件名
if err := viper.ReadInConfig(); err != nil {
return err
}
return nil
}
// LogInfo 初始化日志配置
func LogInfo() {
// 文件命名格式:年-月-日_时分;时间格式化使用数字表示,与java等使用字母的常见形式不一样
file := "./" + time.Now().Format("2006-01-02_1504") + ".log"
logFile, _ := os.OpenFile(file,os.O_RDWR| os.O_CREATE| os.O_APPEND, 0766)
// 自定义日志格式:年-月-日 | 时间 | 文件名+源代码所在行号
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.SetOutput(logFile)
}
model / init.go
MySql数据库初始化
package model
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/spf13/viper"
"log"
)
// 定义全局变量
var ConstDb *sql.DB
func Init() error {
fmt.Println("----------MySql INIT------------")
var err error
// 初始化sql.DB对象,第一个是数据库驱动名,第二个是连接信息的字符串
// sql.DB代表数据库类型,其它语言操作数据库时,需要创建连接,而Go则是创建数据库类型,它不是数据库连接
// sql.Open初始化连接池
ConstDb,err = sql.Open("mysql", viper.GetString("mysql.source_name"))
if nil != err {
return err
}
/**实现连接池的配置*/
// 设置的最大连接数
ConstDb.SetMaxOpenConns(viper.GetInt("mysql.max_open_conns"))
// 设置执行完闲置的连接
ConstDb.SetMaxIdleConns(viper.GetInt("mysql.max_idle_conns"))
//尝试与数据库建立连接,使用完毕后会马上把连接返回连接池
err = ConstDb.Ping()
if nil != err{
return err
}else{
log.Println("MySql startup is ok")
}
return nil
}
router.go
路由信息配置,注意:该路由信息引入了后续blog开发编写的中间件和服务,可以自行配置hello之类的
package router
import (
"github.com/gin-gonic/gin"
"gotest/router/middleware"
"gotest/service"
"net/http"
)
//InitRouter 初始化路由
func InitRouter(g *gin.Engine) {
middlewares := []gin.HandlerFunc{}
// Middlewares
g.Use(gin.Recovery())
g.Use(middleware.NoCache)
g.Use(middleware.Options)
g.Use(middleware.Secure)
g.Use(middlewares...)
// 404 Handler
g.NoRoute(func(c *gin.Context) {
c.String(http.StatusNotFound, "The incorrect API route.")
})
// 路由配置
router := g.Group("/user")
{
// 新增用户数据
router.POST("/addUser", service.AddUser)
// 通过用户名查询用户数据
router.POST("/selectUser", service.SelectUserByName)
}
}
go.mod
在开发过程中GoLand软件自行引入第三方包,并写入go.mod文件