0. 初始化引擎
engine:=gin.Default()
engine.Run(":8090")
1. 数据绑定
1.1 绑定 query 数据
go 参数解析
// 获取 query 中的参数
context.DefaultQuery("key","defaultValue")
// 获取路径参数
// /path/:id
context.Param("id")
// 获取 post form 中的参数
context.PostForm("key")
context.ShouldbBindQuery()
1.2 post 请求参数绑定
var register Register
context.ShouldBind(®ister)
type Register struct{
UserName string `form:"name"`
Phone string `form:"phone"`
Password string `form:"password"`
}
1.3 post json 数据参数绑定
var register Register
context.BindJSON(®ister)
1.4 绑定标签
type Param struct{
Name string `uri:"name" form:"name" header:"name" json:"name" `
}
- ShouldBindUri: 绑定 uri 使用 ‘uri’ 标签
- ShouldBindQuery: 绑定 query 使用 ‘form’ 标签
- ShouldBindHeader: 绑定 header 使用 ‘header’ 标签
- ShouldBindWith(param, binding.Form): 绑定 form 使用 ‘form’ 标签
- ShouldBindJSON: 绑定 json 使用 ‘json’ 标签
1.5 多次绑定
要想多次绑定,可以使用 c.ShouldBindBodyWith.
调用此方法,会将 body 中的参数进行缓存,方便下次调用。因为 request.body 中的数据只能被读取一次。
func SomeHandler(c *gin.Context) {
objA := formA{}
objB := formB{}
// 读取 c.Request.Body 并将结果存入上下文。
if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil {
c.String(http.StatusOK, `the body should be formA`)
// 这时, 复用存储在上下文中的 body。
} else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
c.String(http.StatusOK, `the body should be formB JSON`)
// 可以接受其他格式
} else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil {
c.String(http.StatusOK, `the body should be formB XML`)
} else {
...
}
}
1.6 数据验证
Gin使用 go-playground/validator/v10 进行验证。 参考文档
https://pkg.go.dev/github.com/go-playground/validator/v10#section-readme
1.7 文件上传
- 上传单个文件
func (f *FileController) UploadOne(c *gin.Context) {
// 单文件
file, _ := c.FormFile("file")
log.Println(file.Filename)
dst := "./upload/" + file.Filename
// 上传文件至指定的完整文件路径
c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
}
- 上传多个文件
// Multipart form
form, _ := c.MultipartForm()
files := form.File["upload[]"]
for _, file := range files {
log.Println(file.Filename)
dst := "./upload/" + file.Filename
// 上传文件至指定目录
c.SaveUploadedFile(file, dst)
}
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
2. 数据返回格式
2.1 返回 string 和 []byte
context.Writer.Write()
context.Writer.WriteString()
2.2 返回 json
map 对象返回
context.Writer.JSON(200,map[string]interface{}{
"code":1,
"message":"ok",
"data":"content"
})
struct 对象返回
type Response struct{
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
resp:=Response{Code:1,Message:"ok",Data:"true"}
context.JSON(200,&resp)
2.3 返回 html 模版
// 设置 html 目录
engine.LoadHTMLGlob("./html/*")
// 设置静态资源目录
engine.Static("/img","./img")
// 返回 html 数据
context.HTML(http.StatusOK,"index.html",gin.H{
"fullPath":fullPath,
})
3. 请求路由组
engine.Group()
4. 中间件 middleware
engine.Use()
4.1 自定义中间件
类似 springboot 中的拦截器
接收到请求后,先进入中间件,然后再进入处理函数
处理函数完成,再次进入中间件,最后返回客户端
- func 函数
- 返回类型为 HandleFunc
func RequestInfos() gin.HandleFunc{
return func(context *gin.Context){
}
}
// 所有接口都使用中间件
engine.Use(RequestInfos())
// 单个接口使用中间件
engine.GET("/url",RequestInfos(),func (context *gin.Context)){
// 功能实现
})
context.Next
Next 之前的代码在进入处理函数前执行
Next 之后的代码在处理函数完成后执行
// 进入 handle 前的逻辑
context.Next()
// 执行完 handle 后的逻辑
5. gin 数据库使用
gorm
安装
go get -u githu.com/jinzhu/gorm
连接数据库
不同的数据库需要不同的驱动程序,gorm 提供了一些默认的驱动
import _ "github.com/jinzhu/gorm/dialects/mysql"
// import _ "github.com/jinzhu/gorm/dialects/postgres"
// import _ "github.com/jinzhu/gorm/dialects/sqlite"
// import _ "github.com/jinzhu/gorm/dialects/mssql"
MySql
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
PostgreSQL
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
SQLite
import (
"gorm.io/driver/sqlite" // Sqlite driver based on GGO
// "github.com/glebarez/sqlite" // Pure go SQLite driver, checkout https://github.com/glebarez/sqlite for details
"gorm.io/gorm"
)
// github.com/mattn/go-sqlite3
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
SQL Server
import (
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
)
// github.com/denisenkom/go-mssqldb
dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})
Clickhouse
https://github.com/go-gorm/clickhouse
import (
"gorm.io/driver/clickhouse"
"gorm.io/gorm"
)
func main() {
dsn := "tcp://localhost:9000?database=gorm&username=gorm&password=gorm&read_timeout=10&write_timeout=20"
db, err := gorm.Open(clickhouse.Open(dsn), &gorm.Config{})
// Auto Migrate
db.AutoMigrate(&User{})
// Set table options
db.Set("gorm:table_options", "ENGINE=Distributed(cluster, default, hits)").AutoMigrate(&User{})
// 插入
db.Create(&user)
// 查询
db.Find(&user, "id = ?", 10)
// 批量插入
var users = []User{user1, user2, user3}
db.Create(&users)
// ...
}
连接池
GORM 使用 database/sql 维护连接池
sqlDB, err := db.DB()
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)
模型定义
type Model struct{
Id uint `gorm:"primary_key"`
Name string
}
// 默认表名是结构体名称的复数 models
// 自定义表名
func (m Model)TableName()string{
return "model"
}
// 自定义列名
type User struct{
Id string `gorm:"primary_key"`
Name string `gorm:"column:name"`
CreateTime time.Time `gorm:"column:create_time"`
}