Go微服务实践之增删改查

Wesley13
• 阅读 734

从此篇文章开始,我们来陆续介绍 go-zero 开发一个项目所需要的组件和开发实践。

首先我们从 model 层开始,来说说go-zero 的API以及封装细节。首先 model 层连接的API集中在core/stores。我们先来看看操作 mysql 这类数据库,API方法我们来到 core/stores/sqlx,所以接下来用几篇的文章总体介绍一下 sqlx 的使用和设计思想。

快速使用

func main() {
  // 1
  const datasource = "user:password@/dbname"
  mysqlDB := sqlx.NewMysql(datasource)
  // 2
  um := model.NewUserModel(mysqlDB,"User")
  // 3
  ul := logic.NewUserLogic(um)
  // 4
  engine.AddRoutes(nginxApi(ul))
  engine.Start()
}

// NewUserModel,NewUserLogic 类似
func NewUserModel(conn sqlx.SqlConn, table string) *UserModel {
    return &UserModel{conn: conn, table: table}
}

// nginxApi将logic注入到handle,同时绑定路由和handler
func nginxApi(ul *logic.UserLogic) []rest.Route {
    return []rest.Route{
        {
            Method:  http.MethodGet,
            Path:    "/user/:id", // /user/54er6;
            Handler: handler.NewUserHandler(ul).GetUserById,
    }
}

总结一下:

  1. NewMysql 创建数据库连接
  2. 创建相应的 model,并将连接传入「相应的 NewModel 需要开发者编写」
  3. model 是为上一层 logic 提供服务
  4. logic 注入到 handler 中,同时 handler 与路由绑定,开启 Server

这样 model-logic-handler 最简单的结构就出来了。然后来看看在 model 层如何进行数据操作:

var userBuilderQueryRows = strings.Join(builderx.FieldNames(&User{}), ",")

type User struct {
  Avatar string `db:"avatar"` // 头像
  UserName string `db:"user_name"` // 姓名
  Sex int `db:"sex"` // 1男,2女
  MobilePhone string `db:"mobile_phone"` // 手机号
}

func (um *UserModel) Insert(user *User) (int64, error) {
  const insertsql = `insert into `+um.table+` (`+userBuilderQueryRows+`) values(?, ?, ?)`
  // insert「delete使用方式一致」
  res, err := um.conn.Exec(insertsql, user.Avatar, user.UserName, user.Sex, user.MobilePhone)
  if err != nil {
    logx.Errorf("insert User Position Model Model err, err=%v", err)
    return -1, err
  }
  id, err := res.LastInsertId()
    if err != nil {
        logx.Errorf("insert User Model to Id  parse id err,err=%v", err)
        return -1, err
    }
    return id, nil
}

func (um *UserModel) FindOne(uid int64) (*User, error) {
  var user User
  // query
  const querysql = `select `+userBuilderQueryRows+` from `+um.table+` where id=? limit 1`
    err := um.conn.QueryRow(&user, querysql, uid)
    if err != nil {
        logx.Errorf("userModile.findOne error ,id=%d,err=%s", uid, err.Error())
        if err == sqlx.ErrNotFound {
            return nil, ErrNotFound
        }
        return nil, err
    }
    return &user, nil
}
  • insert/update/deleteconn.Exec(insertsql/updatesql/deletesql, args...)
  • queryconn.QueryRow(&model, querysql, args...)

上述就是最简单的 crud 的结构:首先是构建 model ,然后操作 model 进行操作。

代码结构

文件名

作用

bulkinserter.go

批量插入

mysql.go

NewMysql

orm.go

解析,序列化model的操作

sqlconn.go

抽象crud操作的接口

tx.go

事务操作

sqlconn.go 的相互接口关系:

Go微服务实践之增删改查

可以看出:commonSqlConntxSession 是真正实现的地方。先从 API 的功能整体介绍一下:

API

参数

作用

Exec(query, args...)

sql, sql参数

insert/update/delete

Prepare(query)

sql

预编译sql

QueryRow(&model, query, args...)

model, sql, sql参数

查询一行数据同时赋值给「model」

QueryRowPartial(&model, query, args...)

model, sql, sql参数

功能同上,但是select sql可以只选取model的部分column「映衬Partial」

QueryRows/QueryRowsPartial

同上

查询多行API

Transact(func(session Session) error)

事务操作

将参数中的操作用事务包裹,开发者只需专注参数中的函数编写

总结

go-zerosqlx 屏蔽了go原生的sql操作,开发者只需关注sql编写和业务封装的数据对象,不需要像原生开发中需要手动prepare,赋值数据时Scan。

本节只是简略介绍了接口的相互关系以及开发者平时关注的API,下节将着重分析go-zero是怎么帮你赋值数据,同时在并发大的情况下,如何不让流量直接把你的数据库打死

参考

欢迎大家使用 go-zero

项目地址:

https://github.com/tal-tech/go-zero

https://gitee.com/kevwan/go-zero

如果觉得文章不错,欢迎 github 点个 star 🤝

点赞
收藏
评论区
推荐文章
Irene181 Irene181
2年前
手机自动化测试IDE-----Airtest实战篇
大家好,我是IT共享者,人称皮皮。上篇文章我们介绍了,这篇我们来讲讲Airtest实际操作方法,一起来看看吧。前言前面我们讲到了Airtest的基础知识,,,今天我们就来说说Airtest的具体操作方法吧,让我们轻松实现软件自动化,真正解放我们的双手吧。基本操作我们就是用我们说的跨平台API模块中的方法来操作我们的APK,下面来看下吧。我们先点击To
Python进阶者 Python进阶者
2年前
手机自动化测试IDE-----Airtest实战篇
大家好,我是IT共享者,人称皮皮。上篇文章我们介绍了,这篇我们来讲讲Airtest实际操作方法,一起来看看吧。前言前面我们讲到了Airtest的基础知识,,,今天我们就来说说Airtest的具体操作方法吧,让我们轻松实现软件自动化,真正解放我们的双手吧。基本操作我们就是用我们说的跨平台API模块中的方法来操作我们的APK,下面来看下吧。我们先点击Touc
刘望舒 刘望舒
2年前
Android解析WindowManagerService(一)WMS的诞生
Android框架层Android系统服务WindowManagerServiceAndroid框架层本文首发于微信公众号「后厂技术官」前言此前我用多篇文章介绍了WindowManager,这个系列我们来介绍WindowManager的管理者WMS,首先我们先来学习WMS是如何产生的。本文源码基于Android8.0,与Android7.1.2
kenx kenx
2年前
个人博客开发之blog-api项目统一结果集api封装
前言由于返回jsonapi格式接口,所以我们需要通过javabean封装一个统一数据返回格式,便于和前端约定交互,状态码枚举ResultCodejavapackagecn.soboys.core.ret;importlombok.Getter;/@authorkenx@version1.0@date2021/6/1715:35
Wesley13 Wesley13
2年前
go
本文有『Go开源说』第三期gozero直播内容修改整理而成,视频内容较长,拆分成上下篇,本文内容有所删减和重构。大家好,很高兴来到“GO开源说”跟大家分享开源项目背后的一些故事、设计思想以及使用方法,今天分享的项目是gozero,一个集成了各种工程实践的web和rpc框架。我是Kevin,gozero作者,我的github
Stella981 Stella981
2年前
Python之路【第十七篇】:Django【进阶篇 】(转自银角大王博客)
Model到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:创建数据库,设计表结构和字段使用MySQLdb来连接数据库,并编写数据访问层代码业务逻辑层去调用数据访问层执行数据库操作!(https://oscimg.oschina.net/oscnet/2f863fee384e3d877
Stella981 Stella981
2年前
Go orm框架gorm学习
之前咱们学习过原生的Go连接MYSQL的方法,使用Go自带的"database/sql"数据库连接api,"github.com/gosqldriver/mysql"MYSQL驱动,通过比较原生的写法去写sql和处理事务。目前开源界也有很多封装好的orm操作框架,帮我们简省一些重复的操作,提高代码可读性。gorm就是这样的一款作品,我们来学习
Stella981 Stella981
2年前
Hibernate反射DAO模式
在持久层框架中,如果我们要像简单的JDBC连接数据库那样写一个通用的Dao方法的话,那么把JDBC简单的业务逻辑搬到hibernate持久层框架中,当然是不可能的,这里主要的问题就在于hibernate持久层框架中,因为它不是像JDBC那样简单的增删改查的编写,而是要针对实体类映射配置文件来对照数据库表字段进行操作,而且操作是面向对象的查询,不是简单的sql
API 小达人 API 小达人
9个月前
如何开发 RESTful、GraphQL 和 SOAP 等不同类型的 API ?
本指南将详尽探讨API开发的基本要素,包括涉及的概念、类型和协议,以及可用的最佳实践和工具。我们将从揭示API在现代软件开发中的作用开始,阐明它们如何促进不同软件组件之间的无缝通信。之后,我们将深入研究各种API类型,如RESTful、GraphQL和SOAP,并分析它们独特的特点和理想用例。接下来将讨论API设计的关键方面,重点关注API安全性、可扩展性和可维护性。我们将讨论常见的身份验证和授权机制、速率限制以及API版本控制等其他基本主题。最后,我们将介绍领先的API开发工具和框架以及文档和测试的价值,确保你具备开发高质量、高效且安全API所需的知识和资源。
笑面虎 笑面虎
2星期前
【13章】Go微服务精讲:Go-Zero全流程实战即时通讯
【13章】Go微服务精讲:GoZero全流程实战即时通讯gozero是一个集成了各种工程实践的web和rpc框架。通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验。gozero中的api,rpc,数据库等涉及的代码,都可以给我们一键生成,无需耗