这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
一、本堂课主要内容
-
Go框架三件套
- Gorm
- Kitex
- Hertz
二、知识点详解
三件套简介
-
Gorm
Gorm是功能强大的ORM框架,在字节内部有广泛的使用和丰富的开源拓展
-
Kitex
Kitex是字节内部Golang微服务RPC框架,具有高性能、强可拓展性的特点,支持多协议并且具有丰富的开源拓展
-
Hertz
字节内部的HTTP框架,参考了其他开源框架的优势,结合字节内部自身需求,具有高易用性、高性能和高可拓展的特点
三件套的基本使用
Gorm的基本使用
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Product struct {
gorm.Model
Code string
Price uint
}
func (p Product) TableName() string {
return "product"
}
func main() {
dsn := "root:root@tcp(101.43.254.215:3306)/zzy_demo?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Migrate the schema
db.AutoMigrate(&Product{})
// Create
db.Create(&Product{Code: "D42", Price: 100})
// Read
var product Product
db.First(&product, 1) // find product with integer primary key
db.First(&product, "code = ?", "D42") // find product with code D42
fmt.Println(product)
// Update - update product's price to 200
db.Model(&product).Update("Price", 200)
fmt.Println(product)
// Update - update multiple fields
db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // non-zero fields
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
// Delete - delete product
//db.Delete(&product, 1)
}
使用navicat查看表和数据是否写入数据库:
Gorm约定:使用ID的字段作为主键;使用CreatedAt、UpdatedAt字段作为创建、更新时间;使用结构体的蛇形负数作为表名;使用字段名的蛇形作为表名
Gorm连接到数据库:
这里以mysql为例,Gorm支持MySQL,PostreSQL,SQLite和SQL Server,几乎囊括了所有主流数据库,[详细信息参考](连接到数据库 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.)
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{})
}
定义默认值:
type Product struct {
gorm.Model
ID uint `gorm:"primarykey"`
Code string `gorm:"default:golang"`
Price uint `gorm:"default:100"`
}
查询: [参考](Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国 (studygolang.com))
更新: [参考](更新 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.)
删除: 参考
事务:
Hook:
Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。
如果您已经为模型定义了指定的方法,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务。
Hook方法的函数签名应该是 func(*gorm.DB) error
// 开始事务
BeforeSave BeforeCreate
// 关联前的 save
// 插入记录至 db
// 关联后的
save AfterCreate
// 提交或回滚事务
AfterSave
代码实例:
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
u.UUID = uuid.New()
if !u.IsValid() {
err = errors.New("can't save invalid data")
}
return
}
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
if u.ID == 1 {
tx.Model(u).Update("role", "admin")
}
return
}
[参考](Hook | GORM - The fantastic ORM library for Golang, aims to be developer friendly.)
Gorm 性能提高:
Kitex的基本使用
由于暂时没有针对 Windows 做支持,如果本地开发环境是 Windows 建议使用 WSL2
假如你的虚拟机还没有配置GO开发环境,参考以下信息:
准备 Golang 开发环境
- 如果您之前未搭建 Golang 开发环境, 可以参考 Golang 安装
- 推荐使用最新版本的 Golang,我们保证最新三个正式版本的兼容性(现在 >= v1.16)。
- 确保打开 go mod 支持 (Golang >= 1.15时,默认开启)
- kitex 暂时没有针对 Windows 做支持,如果本地开发环境是 Windows 建议使用 WSL2
安装代码生成工具
首先,我们需要安装使用本示例所需要的命令行代码生成工具:
- 确保
GOPATH环境变量已经被正确地定义(例如export GOPATH=~/go)并且将$GOPATH/bin添加到PATH环境变量之中(例如export PATH=$GOPATH/bin:$PATH);请勿将GOPATH设置为当前用户没有读写权限的目录 - 安装 kitex:
go install github.com/cloudwego/kitex/tool/cmd/kitex@latest - 安装 thriftgo:
go install github.com/cloudwego/thriftgo@latest
安装成功后,执行 kitex --version 和 thriftgo --version 应该能够看到具体版本号的输出(版本号有差异,以 x.x.x 示例):
$ kitex --version
vx.x.x
$ thriftgo --version
thriftgo x.x.x
基本使用
创建Client和发起请求
Kitex服务注册与发现
Hertz的基本使用
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
// Default creates a hertz instance with default middlewares.
h := server.Default()
// GET is a shortcut for router.Handle("GET", path, handle).
h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{"message": "pong"})
})
// Spin runs the server until catching os.Signal or error returned by h.Run().
h.Spin()
}
路由
Hertz 提供了 GET、POST、PUT、DELETE、ANY 等方法用于注册路由,分别用于注册对应的HTTP Method
示例程序:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main(){
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
h.StaticFS("/", &app.FS{Root: "./", GenerateIndexPages: true})
h.GET("/get", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "get")
})
h.POST("/post", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "post")
})
h.PUT("/put", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "put")
})
h.DELETE("/delete", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "delete")
})
h.PATCH("/patch", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "patch")
})
h.HEAD("/head", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "head")
})
h.OPTIONS("/options", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "options")
})
h.Any("/ping_any", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "any")
})
h.Handle("LOAD","/load", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "load")
})
h.Spin()
}
此外Hertz还支持路由组、参数路由和通配路由等等功能,[具体参考](路由 | CloudWeGo)
[其他内容也一并参考文档](基本特性 | CloudWeGo)