这是我参与【第五届青训营】伴学笔记创作活动的第五天,此篇概述一下在青训营学习的go项目框架知识。
Web/RPC/ORM 三件套
-
三件套介绍:Gorm, Kitex, Hertz
-
Gorm 的基本使用见上一篇文章 【GO 数据库 | 青训营笔记】 - 掘金 (juejin.cn)
Gorm 通过驱动来连接数据库
-
GORM 事务:提供了 Begin、Commit、Rollback 方法用于使用事务
db, err := gorm.Open(mysql.Open(""), &gorm.Config{}) if err != nil { panic("failed to connnect datebase") } tx := db.Begin() // 开始事务 if err = tx.Create(&User{Name: "name"}).Error; err != nil { tx.Rollback() // 错误回滚 return } // 提交事务 tx.Commit()提供 Tansaction 方法用于自动提交事务,避免用户漏写Begin、 Commit、Rollback 导致信息泄露等
if err = db.Transaction(func(tx *gorm.DB) error { if err = tx.Create(&User{Name: "name"}).Error; err != nil { return err } }) ; err!=nil { return }提供 Hook, 在创建,查询,更新,删除等操作之前之后自动调用的函数,如果任何 Hook 返回错误,GORM 将停止之后的事务并回滚事务。
func (u *User) BeforeCreate(tx *gorm.DB) (err error) { if u.Age < 0 { return error.New("can't save invalid data") } return } func (u *User) AfterCreate(tx *gorm.DB) (err error) { return tx.Create(&User{ID: u.ID, Name: u.Name, Password: u.Password}) } -
性能优化
db, err := gorm.Open(mysql.Open(""), &gorm.Config{ SkipDefaultTransaction: true, // 关闭默认事务 PrepareStmt: true // 缓存预编译语句 }) // 提高调用速度
-
-
Kitex
-
使用 IDL 定义服务与接口
namespace go api struct Request { 1: string message } struct Response { 1: string message } service Echo { Response echo(1: Request req) } -
Kitex 生成代码
kitex -module example -service example echo.thrift -
服务器默认监听 8888 端口
type EchoImpl struct {} func(s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Reponse, err error) { return } -
Kitex Client 发送请求
// 创建 Client c, err := echo.NewClient("example", client.WithHostPorts("0.0.0:8888")) if err != nil { log.Fatal(err) } // 发起请求 req := &opi.Request{Message: "my request"} resp, err := c.Echo(context.Background(), req, callopt.WithRPCTimeout(3*time.Second)) if err != nil { log.Fatal(err) } log.Println(resp) -
Kitex 服务注册与发现
type HelloImpl struct {} func(h *HelloImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Reponse, err error) { resp = &api.Response { Message: req.Message } } // 服务端 func main() { r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"}) if err != nil { log.Fatal(err) } // 服务注册:服务名 "Hello" server := hello.NewServer(new(HelloImpl), server.WithRegistry(r), server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ ServiceName: "Hello" })) err = server.Run() if err != nil { log.Fatal(err) } } // 客户端 func main() { r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"}) if err != nil { log.Fatal(err) }" client := hello.MustNewClient("Hello", client.WithResolver(r)) // 初始化 for { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) // 设置超时 resp, err := client.Echo(ctx, &api.Request{Message: "Hello"}) // 发送请求 cancel() if err != nil { log.Fatal(err) } log.Println(resp) time.Sleep(time.Second) } }
-
-
Hertz
-
Hertz 基本使用:
// 服务监听8080端口,并注册一个GET方法的路由函数 func main() { h := server.Default(server.WithHostPorts("127.0.0.1:8080")) h.GET("/ping", func(c context.Context, ctx *app.RequestContext) { ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"}) }) h.Spin() } func RegistreRoute(h *server.Hertz) { // 不同方法注册路由 GET, POST,PUT, 以post为例 h.POST("/post", func(ctx context.Context, c *app.RequestContext){ c.String(consts.StatusOK, "post") }) } -
Hertz 中间件
func MyMiddleware() app.HandlerFunc { return func(ctx context.Context, c *app.RequestConstext) { fmt.Println("pre-handle") // 前半段 c.Next(ctx) // 执行下一个中间件 fmt.Println("post-handle") // 后半段 } } func main(){ // 服务端的中间件示例 h := server.Default(server.WithHostPorts("127.0.0.1:8080")) h.Use(MyMiddleware()) h.GET("/middleware", func(ctx context.Context, c *app.RequestConstext){ c.String(consts.StatusOK, "post") }) h.Spin() } -
Hertz Client : 提供了 HTTP Client 用于帮助用户发送 HTTP 请求
c, err := client.NewClient() if err != nil { return } // 发送 http get 请求 status, body, _ := c.Get(context.Background(), nil, "http://....") fmt.Printf("status=%v body=%v\n", status, string(body)) // 发送 http post 请求 var postArgs protocol.Args postArgs.Set("args", "a") // 发送post args status, body, _ = c.Post(context.Background, nil, "http://....") fmt.Printf("status=%v body=%v\n", status, string(body))
-