这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
前言
下面笔记简单记录我作为一个初学者使用框架的过程。
Hertz 初体验
首先在 官网 上下载安装 Hertz,因为后面的 Kitex 只能运行在 Linux 系统上,所以我直接使用 WSL2 环境。
我直接在 WSL2 上运行下面的安装代码:
go install github.com/cloudwego/hertz/cmd/hz@latest
然后使用 hz version v0.1.0,查看是否安装成功,就发现下面的问题,command not found
然后想到可能是没有正确配置好 go 的环境,也就是官网最开始提示的地方:
- 确保
GOPATH环境变量已经被正确地定义(例如export GOPATH=~/go)并且将$GOPATH/bin添加到PATH环境变量之中(例如export PATH=$GOPATH/bin:$PATH);请勿将GOPATH设置为当前用户没有读写权限的目录
然后我这里踩了一个坑,我之前设置 GOPATH 的时候,放到了一个没有权限的目录,而且修改了 /etc/profile 文件,导致上面设置完之后重新打开一个终端就无法正常使用 hz 命令了,把 /etc/profile 修改一下上面的问题就解决了。
重新配置了环境变量之后,这个问题就解决,再重新下载安装就可以发现下面的 hz version 能正常运行了。
然后可以跟着官网快速创建一个 demo,因为官网写的比较详细,这里就不赘述了。
我们可以直接编译并启动 Server,出现下面的情况说明已经成功启动了。
然后新开一个窗口,输入 curl http://127.0.0.1:8888/ping 对接口进行测试。
可以发现测试成功,说明前面的安装没有问题。
Kitex 初体验
以下操作主要参考官方文档 快速开始 | CloudWeGo。
首先是安装 kitex 和 thriftgo:
- 安装 kitex:
go install github.com/cloudwego/kitex/tool/cmd/kitex@latest - 安装 thriftgo:
go install github.com/cloudwego/thriftgo@latest
有了前面 GOPATH 环境变量的设置,这里就容易很多,安装成功后可以查看 version。
下载官方提供的示例代码:
git clone https://github.com/cloudwego/kitex-examples.git
然后根据官方提示直接启动:
- 进入示例仓库的
hello目录 :cd kitex-examples/hello- 运行 server:
go run .- 运行 client:另起一个终端后,
go run ./client
运行结果如下:
服务端:
客户端:
接下来根据文档添加一个新的
Add 方法,最后成功运行如下:
Gorm 初体验
模型
Gorm 默认定义了一个结构体,包括字段 ID、CreatedAt、UpdatedAt、DeletedAt。
// gorm.Model 的定义
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
gorm.Model 只是官方的一个约定,具体实现可以将其嵌入到自己实现的结构体当中。
Gorm 使用的时候需要连接到数据库中,我这里用的是 MySQL,下面参考 官方文档 连接到 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{})
}
CRUD
接下来是一些简单的 CRUD 操作,我这里以一个简单的小例子为主,详细手册还是看下 官方文档。
创建
首先是建立数据模型,我这里创建一个 Student 结构体,嵌套了 gorm.Model,Student 包括两个属性姓名和成绩。
type Student struct {
gorm.Model
Name string `gorm:"name"`
Grade uint `gorm:"grade"`
}
然后是连接到数据库,注意修改 dsn 中的数据库相关的信息:
// 参考 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{})
if err != nil {
panic("failed to connect database")
}
下面我们创建一个名为 Silas,年龄 18,成绩 95 的数据,然后写入到数据库中。其中迁移的作用是自动为数据库创建一个 Student 结构体对应的表,就不需要我们手动去创建了。
// 迁移 schema
db.AutoMigrate(&Student{})
stu := Student{Name: "Silas", Age: 18, Grade: 95}
result := db.Create(&stu) // 通过数据的指针来创建
fmt.Println(stu.ID) // 返回插入数据的主键
fmt.Println(result.Error) // 返回 error
fmt.Println(result.RowsAffected) // 返回插入记录的条数
下面是运行后截图:
同时也可以在 MySQL 中发现新建了一个表和一条数据:
为了后续查询方便,这里在添加几条数据,gorm 可以通过切片直接创建数据:
var students = []Student{{Name: "Tom", Age: 22, Grade: 98}, {Name: "Alice", Age: 19, Grade: 92}, {Name: "Bob", Age: 25, Grade: 90}}
db.Create(&students)
for _, stu := range students {
fmt.Println(stu.ID) // 2,3,4
}
查询
GORM 提供了 First、Take、Last 方法,以便从数据库中检索单个对象。当查询数据库时它添加了 LIMIT 1 条件,且没有找到记录时,它会返回 ErrRecordNotFound 错误。
result := db.First(&stu)
fmt.Println(result)
fmt.Println(result.RowsAffected) // 返回找到的记录数
fmt.Println(result.Error) // returns error
// 获取一条记录,没有指定排序字段
// SELECT * FROM students LIMIT 1;
result = db.Take(&stu)
fmt.Println(result)
fmt.Println(result.RowsAffected) // 返回找到的记录数
fmt.Println(result.Error) // returns error
// 获取最后一条记录(主键降序)
// SELECT * FROM students ORDER BY id DESC LIMIT 1;
result = db.Last(&stu)
fmt.Println(result)
fmt.Println(result.RowsAffected) // 返回找到的记录数
fmt.Println(result.Error) // returns error
// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)
注意上面的三条语句要分开执行,不然最后只会留下第一个查询到的数据。
Gorm 还提供了 where 子句查询,下面找到名字为 Bob 的字段:
// 获取第一条匹配的记录
db.Where("name = ?", "Bob").First(&stu)
fmt.Println(stu)
更多查询用法请见 官方文档
更新
更新一条数据,可以先获得待修改操作的对象,修改后通过 save 方法更新数据,下面代码执行过后,可以发现数据库中对应的信息已经更新了。
db.First(&stu)
stu.Name = "silas-2"
stu.Age = 30
db.Save(&stu)
删除
删除一条记录时,删除对象需要指定主键,否则会触发 批量 Delete,例如:
// stu 的 ID 是 `1`
// DELETE from students where id = 1;
db.Delete(&stu)
// 带额外条件的删除
// DELETE from students where id = 1 AND name = "Silas-2";
db.Where("name = ?", "Bob").Delete(&stu)
上面两条语句执行一条过后,Silas-2 这条数据就被删除了,但是由于 Student 结构体嵌入了 gorm.Model,此时包含了 deleted_at 字段,它获得一个软删除的能力,也就是只在 deleted_at 字段上面添加一个删除时间,但是并不实际从数据库中删除,此时也无法查询到数据。
可以使用 Unscoped 永久删除匹配的记录。
db.Unscoped().Delete(&stu)
小结
以上就是我作为初学者初次使用 Go 三个框架的体验,个人感觉刚开始看着比较懵,但是自己动手实践一下,发现其实并没有想像中的那么难,当然目前只是浅尝辄止,后续更深入的学习还是要多看官方文档,多写代码。