postgres与golang点点滴滴 | 青训营笔记

简介: postgres与golang点点滴滴 | 青训营笔记

前言

在golang中使用数据库主要依赖database/sql库以及pg的驱动库。而目前我们常用的pg的驱动库是 github.com/lib/pq

这里我想说的不是如何去使用它们,毕竟人家文档已经很详细了,这里主要总结了一下自己日常使用中学到的一些技巧。

相同标记重复使用

database/sql库没有规定查询字符串中参数标记的任何特定格式,pq使用了postgres - native序号,像下面例子一样,相同的标记可以被重复使用,用于相同的参数:

// $2 使用了两次 都标记的值是64
rows, err := db.Query(`SELECT name FROM users WHERE favorite_fruit = $1
    OR age BETWEEN $2 AND $2 + 3`, "orange", 64)

操作时返回ID

pq不支持database/sqlLastInsertId()方法,所以当你需要插入(更新or删除)数据后获取自增长的id值时,你可以利用pg的RETURNING语法:

var userid int
err := db.QueryRow(`INSERT INTO users(name, favorite_fruit, age)
    VALUES('beatrice', 'starfruit', 93) RETURNING id`).Scan(&userid)

插入时存在更新

在数据看操作时,很多时候时候会存在唯一冲突,主键冲突等等,而我们又是需要在冲突时更新数据或者其他操作,这时我们可以这样:

// 其中name是唯一的,当name冲突时,更新其他字段
err := db.Exec(`INSERT INTO users(name,favorite_fruit,age)
    VALUES($1, $2, $3) 
    ON CONFLICT (name) DO UPDATE 
        SET favorite_fruit=$2,
            age=$3`)
// 当然,有时候你有条件更新
err := db.Exec(`INSERT INTO users(name,favorite_fruit,age)
    VALUES($1, $2, $3) 
    ON CONFLICT (name) DO UPDATE 
        SET favorite_fruit=$2 
        WHERE age > $4`)
// 你也可以什么都不做
err := db.Exec(`INSERT INTO users(name,favorite_fruit,age)
    VALUES($1, $2, $3) 
    ON CONFLICT (name) DO NOTHING`)

只有单行数据简化代码

这个其实上面就用到了,就是queryRow。当你确定只取一行数据的时候你可以使用该函数。但是需要注意的是:当你查询的数据为空的时候,他会返回sql.ErrNoRaw错误。

var count int
err := db.QueryRow(`SELECT count(*) FROM users`).Scan(&count)
if err != nil {
    if err == sql.ErrNoRaw {
        count = 0
        ...
    }
    ...
}

结果集中空值处理

在查询的时候,有时候难以保证字段一定有值,如果为空,在scan的时候就会报错,为了解决这种情况,我们可以使用下面这些来代替可能为空的字段。

--- 字符串       sql.NullString
--- bool        sql.NullBool
--- int         sql.NullInt64
--- float       sql.NullFloat64 
--- timestamp   pq.NullTime

这里前面4个go驱动带的,后面是pq库带的。如果你还需要其他类型的,你可以自定义,只要实现Scanner接口就OK了。

查询时需要嵌入数组

在使用pg语句的时候我们常用到WHERE xxx IN ('XXX','XXX'...)这样的IN数组操作,在go中也有对应的操作。

// 查找数组中对应id的所有人名
ids := []int64{12,16,33,55}
rows,err := db.Query(`SELECT name FROM users WHERE id=ANY($1),pq.Int64Array(ids))
...

当然其他类型对应的数组驱动也有

pq.BoolArray

pq.ByteaArray

pq.StringArray

pq.Float64Array

结果集中数组处理

同上,用到上面pq中的数组

var ids := pq.Int64Array{}
err := db.QueryRow(`SELECT array_agg(id) FROM users WHERE "age" > $1`,18).Scan(&ids)
...


目录
相关文章
|
19天前
|
SQL 前端开发 Go
编程笔记 GOLANG基础 001 为什么要学习Go语言
编程笔记 GOLANG基础 001 为什么要学习Go语言
|
Go C# C语言
【GoLang 笔记】遍历 map 时的 key 随机化问题及解决方法
【GoLang 笔记】遍历 map 时的 key 随机化问题及解决方法
|
19天前
|
存储 IDE 编译器
编程笔记 GOLANG基础 005 第一个程序:hello world 使用vscode
编程笔记 GOLANG基础 005 第一个程序:hello world 使用vscode
|
19天前
|
Go 开发工具
编程笔记 GOLANG基础 004 GOLANG常用命令及VSCODE快捷键
编程笔记 GOLANG基础 004 GOLANG常用命令及VSCODE快捷键
|
19天前
|
Go 开发工具 git
编程笔记 GOLANG基础 003 Go语言开发环境搭建
编程笔记 GOLANG基础 003 Go语言开发环境搭建
|
19天前
|
存储 Java Go
编程笔记 GOLANG基础 002 Go语言简介
编程笔记 GOLANG基础 002 Go语言简介
|
12月前
|
存储 JavaScript Linux
开源 Golang 微服务入门二:RPC 框架 Kitex| 青训营笔记
Kitex 字节跳动内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点,在字节内部已广泛使用。如果对微服务性能有要求,又希望定制扩展融入自己的治理体系,Kitex 会是一个不错的选
207 0
开源 Golang 微服务入门二:RPC 框架 Kitex| 青训营笔记
|
12月前
|
SQL 存储 关系型数据库
开源 Golang 微服务入门三:ORM 框架 GORM| 青训营笔记
GORM 是面向 Golang 语言的一种 ORM(持久层)框架,支持多种数据库的接入,此框架弱化了开发者对于 SQL 语言的掌握程度,使用提供的 API 进行底层数据库的访问。使用提供的 API 进
123 0
开源 Golang 微服务入门三:ORM 框架 GORM| 青训营笔记
|
存储 关系型数据库 MySQL
Golang基本语法-掘金课程笔记
Golang基本语法-掘金课程笔记
94 0
Golang基本语法-掘金课程笔记
|
19天前
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
73 0