Go语言-ORM框架Gorm学习 | 豆包MarsCode AI刷题

125 阅读6分钟
  • Go三件套:

Gorm1)快速入门:2)支持的数据库:3)CRUD* 新增数据:* 查询数据:* 更新数据:* 删除数据:软删除(逻辑删除)4)GORM事务5)GORM Hook(类似前后通知):6)性能提高:GORM配置7)扩展生态:

Gorm

1)快速入门:

  • 注意:天然支持sql注入
  • 注意:图右为Gorm的约定,比如结构体如果定义ID变量会被默认为主键

image-20241122134916644

2)支持的数据库:

image-20241122135141256

3)CRUD

* 新增数据:
  • 右上:当存在唯一索引(如id),那么指定为不处理冲突,则create()执行update()更新操作

image-20241122135633820

* 查询数据:

image-20241122140258675

* 更新数据:

image-20241122140643746

* 删除数据:软删除(逻辑删除)

image-20241122141002634

4)GORM事务

  • 简单实现:

image-20241122141453304

  • 推荐方法:Transaction

image-20241122141618463

5)GORM Hook(类似前后通知):

  • hook操作会带有默认事务

image-20241122141759824

6)性能提高:GORM配置

image-20241122170442333

7)扩展生态:

image-20241122170621549

补充:Golang基础语法

  • Go语言基础

一、介绍Go二、基础语法基本格式、编译运行的命令:变量:if else:后面没有括号循环:只有for循环switch case:数组:切片:map:range:函数:指针:修改变量的值结构体:结构体方法:错误处理:error类型,返回值传递,if处理字符串操作:“strings”包打印:“fmt”包,格式字符json操作:“encoding/json”包时间处理:“time”包数字解析:“strconv”包进程信息:“os”、“os/exec”包defer:函数返回前被调用,从后往前三、实战1)猜谜游戏:2)在线词典* 需求:* 实现:3)实现SOCKS5代理:* 小demo:四、语言进阶 - 协程1)协程:Goroutine2)协程间通信:channel3)WaitGroup:协程计算器五、依赖管理1)Go Module介绍:2)go.mod组成:3)依赖关系冲突:选择最低的兼容版本4)依赖分发:Proxy5)go get工具、go mod工具:六、测试1)单元测试:2)Mock3)基准测试:七、项目1)准备:2)查询:


一、介绍Go

image-20241104135039490

二、基础语法

基本格式、编译运行的命令:

image-20241104135619353

变量:

image-20241104135845566

if else:后面没有括号

  • 括号也可以有,编译的时候会去掉

image-20241104135949712

循环:只有for循环

image-20241104140115256

switch case:

image-20241104140343495

数组:

image-20241104140502164

切片:

image-20241104140733464

map:

image-20241104141158708

range:

image-20241104141505990

函数:

image-20241104141648717

指针:修改变量的值

  • 不以指针传入的变量只是拷贝,需要修改值时要传入指针

image-20241104141812412

结构体:

  • 同样有结构体指针,可对属性进行修改,且有时能避免一些大结构体拷贝的开销

image-20241104141953169

结构体方法:

image-20241104142302907

错误处理:error类型,返回值传递,if处理

  • 不同于java的异常,go用返回值代表错误,用if else处理错误

image-20241104142533132

字符串操作:“strings”包

  • 注意一个中文会对应多个字符

image-20241104142625182

打印:“fmt”包,格式字符

image-20241104142747597

json操作:“encoding/json”包

image-20241104143222520

时间处理:“time”包

image-20241104160110598

数字解析:“strconv”包

image-20241104160316369

进程信息:“os”、“os/exec”包

image-20241104160751232

defer:函数返回前被调用,从后往前

image-20241106144144991

三、实战

1)猜谜游戏:

  • 一、生成随机数:注意需要设置随机数种子(时间),不然每次运行都是相同的数字

image-20241104162442939

  • 二、用户输入:用”bufio”包下方法来读取用户输入
  • Ps:后面可以通过scanf更快的读取

image-20241104162812278

  • 三、判断:

image-20241104162932139

  • 四、完整实现:

image-20241104163031193

2)在线词典

* 需求:
  • 运行该方法时,传入单词,方法打印该单词的音标、含义等
  • 考点:需要发送http请求,解析json字符串、代码生成等

image-20241104163209575

* 实现:
  • 一、抓包:在网页中看请求

image-20241104163542257

  • 二、复制请求的curl命令:

image-20241104164107774

  • 三、打开代码生成网址:转换为go语言的请求
  • 由于header比较复杂,少部分代码可能发生编译错误,直接删掉

image-20241104164149322

  • Ps:看看生成的代码(输入为good的情况)

image-20241104165053984

  • 四、改为变量输入(输入不固定):上面代码生成能看出request body的结构,直接创建对应的结构体对象,通过json序列化并转换为byte数组来当作newRequest的参数

image-20241104184745818

  • 五、解析response body,更好的打印出人能看的结果:
  • 和request body一样,最好是写一个对应的结构体,然后后面打印这个返回结果(response body)的一些属性
  • 方法:打开代码生成网站,将抓包的response body的json字符串传进去,就能生成对应的go的结构体

image-20241104185301669

image-20241104185328603

  • 用生成的结构体获取到返回的response body数据,反序列化并直接打印:

image-20241104185449137

  • 六、将打印内容改为需求中需要打印的信息

image-20241104185722998

  • 七、获取该进程(main方法)的变量,取第二个作为参数word,传入打印方法

image-20241104190020328

3)实现SOCKS5代理:

* 小demo:
  • 需求:创建一个基于tcp连接的服务(本机的xxx端口),读取用户端发送的报文(如字符串),返回相同的字符串
  • 重点:怎么实现tcp端口,开放并获取请求的字符串,并处理和打印出来

image-20241104192005116

四、语言进阶 - 协程

1)协程:Goroutine

  • 并发:一个核,多线程抢夺时间片
  • 并行:多个核,多线程一起运行 -> Go能充分发挥多核优势
  • 线程:属于内核态,系统级别,它的创建等操作会重很多
  • 协程(Goroutine):属于用户态,它由go创建和调度,操作轻(轻松应对上万协程)
  • 方法:通过在函数前加上go关键字来为函数创建协程

image-20241104193434764

2)协程间通信:channel

  • CSP:通信与共享内存
  • Go提倡通过通道来共享内存

image-20241104194126042

  • 无缓冲通道:直接传
  • 有缓冲通道:规定队列中的元素数量,满了会有阻塞

image-20241104195110174

  • 通过通道共享内存的具体实现:

image-20241104194947105

  • 补充(不推荐):通过加锁实现并发的安全

image-20241104195344171

3)WaitGroup:协程计算器

  • 前面介绍协程用到的sleep不够优雅(可能出错),可以用WaitGroup更加精确的停止

image-20241104195542143

  • 代码:

image-20241104195649659

五、依赖管理

1)Go Module介绍:

image-20241104200254147

2)go.mod组成:

image-20241104200608072

  • ①go.mod的版本规则:

image-20241104200730641

  • ②直接依赖、间接依赖:

image-20241104200853856

  • ③incompatible:没有go.mod文件且主版本2+的依赖会有该后缀(表示可能有些代码不兼容)

image-20241104201146842

3)依赖关系冲突:选择最低的兼容版本

image-20241104201329357

4)依赖分发:Proxy

  • 通过代理仓库来获取依赖:修改GOPROXY变量实现

image-20241104201553350

5)go get工具、go mod工具:

image-20241104201704559

image-20241104201815297

六、测试

1)单元测试:

  • 一、组成:

image-20241105095429902

  • 二、规则:
  • Ps:如果测试方法不以大写Test开头,ide就不会出现运行的按钮提示

image-20241105095729396

  • 例:

image-20241105095833639

  • 结果:

image-20241105095937696

  • 三、使用第三方assert包进行校验

image-20241105100018442

  • 四、覆盖率

image-20241105100417776

  • 提高覆盖率:

image-20241105100544426

  • tips:代码设计时,函数应单一职责,这使得测试的单元粒度小,而覆盖率会更高

image-20241105100635887

2)Mock

  • 一、单元测试的要求
  • 幂等:每次运行的结果应该一样
  • 稳定:单元测试应该是相互隔离的,我们在任何时候都能运行
  • 而一些复杂的依赖,比如数据库、cache等,由于网络等因素会造成一些问题 -> Mock机制

image-20241105101055037

  • 例:一些问题
  • 函数依赖于一些本地的文件,一旦文件被修改,就不能正常地测试了

image-20241105101334765

  • 一、介绍mock包:monkey
  • 打桩:

image-20241105101657073

  • 例:用Patch()打桩函数ReadFirstLine(),修改逻辑为直接返回值“line110”

image-20241105101855524

3)基准测试:

  • 概念:指测试代码的运行性能、cpu损耗等
  • 例:

image-20241105102313611

image-20241105102605558

  • 扩展:解决rand包性能差问题,介绍一个开源fastrand(适用大部分场景)

image-20241105102728977

七、项目

1)准备:

  • 分层模型:

image-20241105103356445

  • web项目组件:

image-20241105103428062

2)查询:

  • Ps:这里数据存储在本地文件