现在MySQL被Oracle收购之后,有传闻Oracle正在逐步的封闭MySQL,,鉴于此,将来我们也许会选择PostgreSQL而不是MySQL作为项目的后端数据库。
1、驱动
Go实现的支持PostgreSQL的驱动也很多,因为国外很多人在开发中使用了这个数据库。
https://github.com/bmizerany/pq 支持database/sql驱动,纯Go写的
https://github.com/jbarham/gopgsqldriver 支持database/sql驱动,纯Go写的
https://github.com/lxn/go-pgsql 支持database/sql驱动,纯Go写的
在下面的示例中我采用了第一个驱动,因为它目前使用的人最多,在github上也比较活跃。
2、实例代码
数据库建表语句:
复制代码
CREATE TABLE userinfo
(
uid serial NOT NULL,
username character varying(100) NOT NULL,
departname character varying(500) NOT NULL,
Created date,
CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
)
WITH (OIDS=FALSE)
CREATE TABLE userdeatail
(
uid integer,
intro character varying(100),
profile character varying(100)
)
WITH(OIDS=FALSE)
复制代码
看下面这个Go如何操作数据库表数据:增删改查
复制代码
package main
import (
"database/sql"
"fmt"
_ "github.com/bmizerany/pq"
)
func main() {
db, err := sql.Open("postgres", "user=astaxie password=astaxie dbname=test sslmode=disable")
checkErr(err)
//插入数据
stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) RETURNING uid")
checkErr(err)
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
checkErr(err)
//pg不支持这个函数,因为他没有类似MySQL的自增ID
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
//更新数据
stmt, err = db.Prepare("update userinfo set username=$1 where uid=$2")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", 1)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect)
//查询数据
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created string
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
//删除数据
stmt, err = db.Prepare("delete from userinfo where uid=$1")
checkErr(err)
res, err = stmt.Exec(1)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
复制代码
从上面的代码我们可以看到,PostgreSQL是通过$1,$2这种方式来指定要传递的参数,而不是MySQL中的?,另外在sql.Open中的dsn信息的格式也与MySQL的驱动中的dsn格式不一样,所以在使用时请注意它们的差异。
还有pg不支持LastInsertId函数,因为PostgreSQL内部没有实现类似MySQL的自增ID返回,其他的代码几乎是一模一样
Gorm是Go语言开发用的比较多的一个ORM。它的功能比较全:
但是这篇文章中并不会直接看Gorm的源码,我们会先从database/sql分析。原因是Gorm也是基于这个包来封装的一些功能。所以只有先了解了database/sql包才能更加好的理解Gorm源码。
database/sql 其实也是一个对于mysql驱动的上层封装。”github.com/go-sql-driver/mysql”就是一个对于mysql的驱动,database/sql 就是在这个基础上做的基本封装包含连接池的使用
下面这个是最基本的增删改查操作
操作分下面几个步骤:
因为Gorm的连接池就是使用database/sql包中的连接池,所以这里我们需要学习一下包里的连接池的源码实现。其实所有连接池最重要的就是连接池对象、获取函数、释放函数下面来看一下database/sql中的连接池。
DB对象
获取方法
释放连接方法
连接池的实现有很多方法,在database/sql包中使用的是chan阻塞 使用map记录等待列表,等到有连接释放的时候再把连接传入等待列表中的chan 不在阻塞返回连接。
之前我们看到的Redigo是使用一个chan 来阻塞,然后释放的时候放入空闲列表,在往这一个chan中传入struct{}{},让程序继续 获取的时候再从空闲列表中获取。并且使用的是链表的结构来存储空闲列表。
database/sql 是对于mysql驱动的封装,然而Gorm则是对于database/sql的再次封装。让我们可以更加简单的实现对于mysql数据库的操作。
增加:insert into 数据表(字段1,字段2,字段3) values(值1,值2,值3) 修改:update 数据表 set 字段1=值1,字段2=值2 where id=接收到的ID参数 删除:delete from 数据表 where id=接收到的ID参数 看看上面的