Postgresql + Go 备忘录

看到 Postgresql 和 Go 这两者选定的动物作为 logo,不由得想起很久以前的一种说法,在斗兽棋中大象是无畏的存在,但是唯独怕老鼠。
Postgressql 之前倒是经常接触,但是 Go 就得现学现卖了,于是写个备忘录,记录初学 Go 开发踩过的那些坑。

环境

创建一个基本的数据库

1
2
3
4
5
6
7
8
$ sudo pacman -S postgresql
$ sudo systemctl start postgresql
$ sudo -u postgres -i
[postgres]$ initdb --locale $LANG -E UTF8 -D '/var/lib/postgres/data'
[postgres]$ createuser --interactive
$ createdb myDatabaseName
[postgres]$ psql -d myDatabaseName
... # 省略具体创建数据库用户和更改数据库权限等SQL操作

完成安装和创建工作,注意命令使用时所对应的账户和权限,如有需要可将 postgresql.service 添加到开机启动。

连接数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const (
host = "localhost"
port = 5432
user = "cantonres"
password = "resistance"
dbname = "cantonres"
)

func main() {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := gorm.Open("postgres", psqlInfo)
if err != nil {
panic(err)
} else {
fmt.Println("Successfully connected!")
}
defer db.Close()
}

将具体信息改成自己的配置后就可以连接到数据库了,连接成功则会输出Successfully connected!

创建表

这里以创建users这个表为例,并定义形式相应的结构体。

1
2
3
4
5
6
7
8
9
10
type User struct {
ID int `json:"id"`
Username string `json:"username";gorm:"not null"`
GoogleID string `json:"google_id";gorm:"not null;"`
Faction int8 `json:"faction";gorm:"not null"`
IsAdmin bool `json:"is_admin";gorm:"not null"`
Email string `json:"email";gorm:"not null;"`
CreatedAt time.Time `json:"created_at";gorm:"not null;"`
UpdatedAt time.Time `json:"updated_at"`
}

表单操作

以查询某个id的用户个人信息为例,将db和用户id传入以下函数即可,得到的结果在 users 中返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func GetUser(db *gorm.DB, id int) []User {
var users []User // 创建一个元素为 User 类型的切片
db.Where("id = ?", id).Find(&users)

return users
}

func main() {
// ...之前连接数据库的代码省略了

id := 1
users := GetUser(db, id)
fmt.Println(users)
fmt.Println(users[0].Username)
}

更多数据库操作可见 gorm 中文文档

小结

实际上写起来还是挺简单的,主要就是之前对静态语言不熟悉,简单用循环做了个查询速度测试,1w条SELECT语句大概需要耗时2.7s,乍一看比之前 python 写的性能还低(1w条SELECT大概798ms),但是由于 gorm 是 orm,不能这样比的 (gorm 用了连接池,实际上真正并行查询的时候,是可以同时存在多个连接的,循环只是用了一个链接,所以应该之后还有速度加成吧,目前还不怎么会写 go 的并行,等之后姿势水平提高了再尝试一下 Orz<-