Go框架学习 | 青训营笔记

149 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第4天。

引言

今天的课程是关于Go语言的三个框架学习和项目实战,框架分别为Gorm(ORM框架)、Kitex(RPC框架)和Hertz(HTTP框架)。这篇文章主要是针对今天课程的记录和总结。


一、本堂课重点内容

本堂课的知识点

  • Gorm:ORM框架,程序员无需直接编写原生SQL语句,框架采用了数据库连接池
  • Kitex;微服务RPC框架
  • Hertz(HTTP框架),性能远高于Gin
  • 项目实战

二、详细知识点介绍

1. Gorm

下载安装

go get -u gorm.io/gorm

连接数据库(以MySQL为例)

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}

Model

在代码中定义模型(Model)与数据库中的数据表进行映射,在GORM中模型(Models)通常是正常定义的结构体、基本的go类型或它们的指针。

gorm.Model是 gorm中内置定义的一个结构体,包含了一些通用字段

// gorm.Model 的定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

CRUD操作

//定义模型
type User struct {
	ID           int64
	Name         string
	Age          int64
    CreatedAt    time.Time
}

1️⃣增加操作(Create)

func main() {
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  defer db.Close()
  //插入一条数据
  user := User{Name: "q1mi", Age: 18,CreatedAt:time.Now()}
  db.NewRecord(user) // 主键为空返回`true`
  db.Create(&user)   // 创建user
  db.NewRecord(user) // 创建`user`后返回`false`  
  //指定字段进行插入
  db.Select("Name", "Age", "CreatedAt").Create(&user)  
  // INSERT INTO `users` (`name`,`age`,`created_at`) VALUES ("jinzhu", 18, "2020-07-04 11:05:21.775")
    
}

插入多条数据,要利用切片

var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
db.Create(&users)

for _, user := range users {
  user.ID // 1,2,3
}

2️⃣查询操作 (Retrieve)

// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;

// IN
db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');

// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;



// 利用map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;

注意:当通过结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果你的字段值为0''false或者其他零值时,将不会被用于构建查询条件,解决方法利用map进行零值字段查询,例如:

db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)  //这种查询是失败的
// SELECT * FROM users WHERE name = "jinzhu";

//可以利用map
db.Where(map[string]interface{}{"Name": "jinzhu", "Age": 0}).Find(&users)  

3️⃣修改操作(Update)

// 条件更新
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;

// User 的 ID 是 `111`
db.Model(&user{111}).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;

// 根据条件和 model 的值进行更新
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;


//更新多列属性
// 根据 `struct` 更新属性,只会更新非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

// 根据 `map` 更新属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

当没有利用Where方法(没有其他的条件时,避免全局更新),Model中的user还会作为条件 若有Where方法时(有其他筛选条件),Model中的user只是用于传递表名称

4️⃣删除操作(Delete)

注意: 删除记录时,请确保主键字段有值,GORM 会通过主键去删除记录,如果主键为空,GORM 会删除该 model 的所有记录。

// 删除现有记录
db.Delete(&email)
//// DELETE from emails where id=10;
// 带额外条件的删除
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";

2. Kitex

待补充

3. Hertz

由字节跳动开源的高性能的Go HTTP框架,作用类别Gin框架,但Hertz的性能更好

下载:

go install github.com/cloudwego/hertz/cmd/hz@latest	

路由学习

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()
}


支持路由组,路由前缀相同的,设计为一组


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"))
	v1 := h.Group("/v1")
    //  127.0.0.1:8080/v1/get
	v1.GET("/get", func(ctx context.Context, c *app.RequestContext) {
		c.String(consts.StatusOK, "get")
	})
	v1.POST("/post", func(ctx context.Context, c *app.RequestContext) {
		c.String(consts.StatusOK, "post")
	})
	h.Spin()
}


三、实践练习例子

笔记项目 地址:kitex-examples/bizdemo/easy_note at main · cloudwego/kitex-examples (github.com)

待补充

四、课后个人总结

今天这堂课程学习了三个Go语言进行后端开发可以使用到的框架,因为之前是先学习的Java,Java进行后端开发的框架也进行过学习,将两种语言的框架以功能进行对应:Gorm对应MyBatis、Kitex对应SpringCloud、Hertz对应SpringMVC,当然这种对应并不严谨。

五、引用参考

[1] 青训营课程资料

[2] Go语言中文网

[3] GORM - 中文文档

[4] Hertz | CloudWeGo