Gin框架 -- 环境搭建
0. 官方文档
https://gin-gonic.com/zh-cn/docs/
1. 下载
go get github.com/gin-gonic/gin
2. Hello World
gin框架内置了httprouter包,gin中的路由库是基于httprouter实现的
main.go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
// 实例化gin对象
router := gin.Default()
// 设置路由和handler
router.GET("/index", func(context *gin.Context) {
context.String(http.StatusOK, "Hello World")
})
// 监听8002端口
router.Run(":8002")
}
3. 配置
1. 启动配置
直接使用 http.ListenAndServe(),如下所示:
func main() {
router := gin.Default()
http.ListenAndServe(":8080", router)
}
或
func main() {
router := gin.Default()
s := &http.Server{
Addr: ":8080",
Handler: router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
}
2. 数据库连接配置
1. 模块下载
go get gopkg.in/ini.v1
2. 配置文件格式
#数据库类型:mysql/sqlite3
db_type = "mysql"
[mysql]
db_alias = "default"
db_name = "test"
db_user = "root"
db_pwd = "123"
db_host = "127.0.0.1"
db_port = 3306
db_charset = "utf8"
[sqlite3]
db_alias = "default"
db_name = "gin_test.db"
3. 配置文件加载
func main() {
r := gin.Default()
// 读取配置文件
conf, err := ini.Load("./config/my.ini")
if err != nil {
log.Fatal("配置文件读取失败, err = ", err)
}
// 初始化路由路径
router.InitRouter(r)
// 初始化数据库
db := models.InitDB(conf)
defer db.Close()
// 项目的启动端口在这儿设置,也可以从配置文件中读取到这儿
port := ":" + conf.Section("").Key("httpport").String()
if err := r.Run(port); err != nil {
log.Fatal("程序启动失败:", err)
}
}
3. 网站图标
1. 模块下载
go get github.com/thinkerou/favicon
2. 准备图标
在线生成工具, 并放在项目对应目录中
https://boke112.com/tools/toico/
3. 使用
package main
import (
"github.com/gin-gonic/gin"
"github.com/thinkerou/favicon"
"net/http"
)
func main() {
router := gin.Default()
router.Use(favicon.New("./favicon.ico"))
router.GET("/", func(context *gin.Context) {
context.JSON(http.StatusOK, gin.H{"msg": "Hello, World"})
})
router.Run(":8003")
}
4. 静态文件
func main() {
router := gin.Default()
router.Static("/static", "./static") // 静态文件配置
router.StaticFS("/more_static", http.Dir("my_file_system"))
router.StaticFile("/favicon.ico", "./resources/favicon.ico")
// 监听并在 0.0.0.0:8080 上启动服务
router.Run(":8080")
}
5. 模板文件
func main(){
// 加载模板文件
r.LoadHTMLGlob("template/*")
}
6. 日志
func main(){
// 记录到文件。
f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
}
7. IP白名单
func main(){
// 设置信任的客户端IP
r.SetTrustedProxies([]string{"192.168.1.33"})
}
7. 开启DeBug模式
func main(){
// 开启DeBug模式
gin.SetMode(gin.DebugMode)
}
8. 配置文件读取运行端口
func main(){
// 1. 加在配置文件
conf, err := ini.Load("./config/my.ini")
if err != nil {
log.Fatal("配置文件读取失败, err = ", err)
}
// 2. 获取项目运行端口
port := conf.Section("").Key("http_host").String() +":" + conf.Section("").Key("http_port").String()
if err = r.Run(port); err != nil{
fmt.Println("服务端启动错误:",err)
}
}
10. Mysql连接配置
models/initDB.go
package models
import (
"github.com/gogf/gf/os/gfile"
"github.com/jinzhu/gorm"
"gopkg.in/ini.v1"
"log"
"os"
"path"
// 加载MySQL数据库驱动
_ "github.com/go-sql-driver/mysql"
// 加载sqlite3数据库驱动
//_ "github.com/mattn/go-sqlite3"
)
// 全局db对象
var db *gorm.DB
func InitDB(conf *ini.File) *gorm.DB {
var err error
// 数据库类型:mysql/sqlite3
// db_type = "mysql"
dbType := conf.Section("").Key("db_type").String()
// mysql配置信息
mysqlName := conf.Section("mysql").Key("db_name").String() // 数据库名称
mysqlUser := conf.Section("mysql").Key("db_user").String() // 用户名
mysqlPwd := conf.Section("mysql").Key("db_pwd").String() // 密码
mysqlHost := conf.Section("mysql").Key("db_host").String() // 数据库ip地址
mysqlPort := conf.Section("mysql").Key("db_port").String() // 数据库端口
mysqlCharset := conf.Section("mysql").Key("db_charset").String() // 指定字符集
// sqlite3配置信息
sqliteName := conf.Section("sqlite3").Key("db_name").String()
var dataSource string
switch dbType {
case "mysql":
// parseTime=true 表示自动解析为时间
dataSource = mysqlUser + ":" + mysqlPwd + "@tcp(" + mysqlHost + ":" + mysqlPort + ")/" + mysqlName + "?charset=" + mysqlCharset + "&parseTime=true"
db, err = gorm.Open(dbType,dataSource)
case "sqlite3":
dataSource = "database" + string(os.PathSeparator) + sqliteName
if !gfile.Exists(dataSource){
os.MkdirAll(path.Dir(dataSource),os.ModePerm)
os.Create(dataSource)
}
db, err = gorm.Open(dbType,dataSource)
}
if err != nil{
db.Close()
log.Println("数据库加载失败",err)
}
// 设置数据库操作显示原生SQL 语句
Db.LogMode(true)
// 数据库表动态迁移
db.AutoMigrate(&auth.User{})
// 设置数据库连接池空闲连接数
db.DB().SetConnMaxIdleTime(50)
// 打开连接
db.DB().SetMaxOpenConns(100)
// 表明禁用后缀加s
db.SingularTable(true)
return db
}
main.go
func main(){
// 初始化数据库
db := models.InitDB(conf)
defer db.Close()
}
11. 多服务运行
1. 参考博客
https://github.com/gin-gonic/gin/issues/346
2. 多服务代码示例
package main
import (
"log"
"net/http"
"time"
"github.com/gin-gonic/gin"
"golang.org/x/sync/errgroup"
)
var (
g errgroup.Group
)
func router01() http.Handler {
e := gin.New()
e.Use(gin.Recovery())
e.GET("/", func(c *gin.Context) {
c.JSON(
http.StatusOK,
gin.H{
"code": http.StatusOK,
"error": "Welcome server 01",
},
)
})
return e
}
func router02() http.Handler {
e := gin.New()
e.Use(gin.Recovery())
e.GET("/", func(c *gin.Context) {
c.JSON(
http.StatusOK,
gin.H{
"code": http.StatusOK,
"error": "Welcome server 02",
},
)
})
return e
}
func main() {
server01 := &http.Server{
Addr: ":8080",
Handler: router01(),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
server02 := &http.Server{
Addr: ":8081",
Handler: router02(),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
g.Go(func() error {
return server01.ListenAndServe()
})
g.Go(func() error {
return server02.ListenAndServe()
})
if err := g.Wait(); err != nil {
log.Fatal(err)
}
}
3. 在handler中使用goroutine
goroutine机制可以方便地实现异步处理.另外,在启动新的goroutine时,不应该使用原始上下文,必须使用它的只读副本
package main
import (
"log"
"time"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// 1.异步
r.GET("/long_async", func(c *gin.Context) {
// 需要搞一个副本
copyContext := c.Copy()
// 异步处理
go func() {
time.Sleep(3 * time.Second)
log.Println("异步执行:" + copyContext.Request.URL.Path)
}()
})
// 2.同步
r.GET("/long_sync", func(c *gin.Context) {
time.Sleep(3 * time.Second)
log.Println("同步执行:" + c.Request.URL.Path)
})
r.Run(":8000")
}
4. 在中间件中使用goroutine
func main() {
r := gin.Default()
r.GET("/long_async", func(c *gin.Context) {
// 创建在 goroutine 中使用的副本
cCp := c.Copy()
go func() {
// 用 time.Sleep() 模拟一个长任务。
time.Sleep(5 * time.Second)
// 请注意您使用的是复制的上下文 "cCp",这一点很重要
log.Println("Done! in path " + cCp.Request.URL.Path)
}()
})
r.GET("/long_sync", func(c *gin.Context) {
// 用 time.Sleep() 模拟一个长任务。
time.Sleep(5 * time.Second)
// 因为没有使用 goroutine,不需要拷贝上下文
log.Println("Done! in path " + c.Request.URL.Path)
})
// 监听并在 0.0.0.0:8080 上启动服务
r.Run(":8080")
}
4. 配置文件的设置与读取
1. yaml 模块
2. viper 模块
1. 模块安装
go get github.com/spf13/viper
2. 配置文件准备
config/settings.yaml0
mysql:
host: 81.70.168.242
port: 3306
db: gin_demo
user: root
password: 123456
max-idle-conns: 10
max-open-conns: 100
log_level: dev
config: charset=utf8mb4&parseTime=True&loc=Local
system:
host: "0.0.0.0"
port: 8848
env: debug
3. 基本使用
core/conf.go
package core
import (
"fmt"
"github.com/spf13/viper"
)
func InitConfig() {
viper.SetConfigName("settings") // 设置配置的名字
viper.AddConfigPath("config") // 设置配置文件路径
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Sprintf("读取配置文件错误: %s", err))
}
}
main.go
package main
import (
"fmt"
"gin_demo/core"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"net/http"
)
func main() {
// 1. 加载文件
core.InitConfig()
// 使用 viper 读取 yaml 文件中的对应配置名下的所有配置项
fmt.Println(viper.Get("mysql")) // map[string]string 类型
router := gin.Default()
router.GET("/index", func(context *gin.Context) {
context.String(http.StatusOK, "Hello World")
})
// 使用 viper 读取 yaml 文件中 system 配置名中的 host port 配置项
err := router.Run(viper.GetString("system.host") + ":" + viper.GetString("system.port"))
if err != nil {
fmt.Println("服务器启动err: ", err)
return
}
}
python防脱发技巧

浙公网安备 33010602011771号