Go为开发数据库驱动定义了一些标准接口,开发者可以根据定义的接口来开发相应的数据库驱动,只要是按照标准接口开发的代码, 以后需要迁移数据库时,不需要任何修改。
一、database/sql接口
1.1sql.Register
这个存在于database/sql的函数是用来注册数据库驱动的,当第三方开发者开发数据库驱动时,都会实现init函数,在init里面会调用这个Register(name string, driver driver.Driver)
完成本驱动的注册。
//https://github.com/mattn/go-sqlite3驱动
func init() {sql.Register("sqlite3", &SQLiteDriver{})
}
//https://github.com/mikespook/mymysql驱动
// Driver automatically registered in database/sql
var d = Driver{proto: "tcp", raddr: "127.0.0.1:3306"}
func init() {Register("SET NAMES utf8")sql.Register("mymysql", &d)
}
1.2driver.Driver
Driver是一个数据库驱动的接口,他定义了一个method: Open(name string),这个方法返回一个数据库的Conn接口。
type Driver interface {Open(name string) (Conn, error)
}
1.3driver.Conn
type Conn interface {Prepare(query string) (Stmt, error)Close() errorBegin() (Tx, error)
}
1.4driver.Stmt
type Stmt interface {Close() errorNumInput() intExec(args []Value) (Result, error)Query(args []Value) (Rows, error)
}
1.5driver.Tx
type Tx interface {Commit() errorRollback() error
}
1.6driver.Result
type Result interface {LastInsertId() (int64, error)RowsAffected() (int64, error)
}
1.7driver.Rows
type Rows interface {Columns() []stringClose() errorNext(dest []Value) error
}
二、sqlite3
2.1sqlite3创建数据库库lab3.db
2.2创建数据库表
CREATE TABLE `userinfo` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT,`username` VARCHAR(64) NULL,`departname` VARCHAR(64) NULL,`created` DATE NULL
);//这个可以先不创建
CREATE TABLE `userdetail` (`uid` INT(10) NULL,`intro` TEXT NULL,`profile` TEXT NULL,PRIMARY KEY (`uid`)
);
2.3sqlite3数据库访问工具(开源)
Downloads - DB Browser for SQLite
https://sqlitebrowser.org/dl/
2.4代码 增删改查
使用的时候,先把删除的注释,然后看结果
package mainimport ("database/sql""fmt"_ "github.com/mattn/go-sqlite3""time"
)func checkErr(err error) {if err != nil {panic(err)}
}func main() {db, err := sql.Open("sqlite3", "./lab3.db")checkErr(err)//插入数据stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) values(?,?,?)")checkErr(err)//上面对应的参数res, err := stmt.Exec("astaxie", "研发部门", "2023-1-09")res2, err2 := stmt.Exec("root", "测试部", "2023-1-09")checkErr(err)checkErr(err2)id, err := res.LastInsertId()id2, err2 := res2.LastInsertId()checkErr(err)checkErr(err2)fmt.Println(id)fmt.Println(id2)//更新数据stmt, err = db.Prepare("update userinfo set username=? where uid=?")checkErr(err)res, err = stmt.Exec("newastaxie", id)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 intvar username stringvar department stringvar created time.Timeerr = rows.Scan(&uid, &username, &department, &created)checkErr(err)fmt.Println("===========================")fmt.Println(uid)fmt.Println(username)fmt.Println(department)fmt.Println(created)}//删除数据stmt, err = db.Prepare("delete from userinfo where uid=?")checkErr(err)res, err = stmt.Exec(id)checkErr(err)affect, err = res.RowsAffected()checkErr(err)fmt.Println(affect)db.Close()
}
2.5验证结果,先把删除的代码注释,查看效果
三、mysql的使用
3.1测试环境的准备,用这个模拟mysql
3.2登录mysql工具navicat
3.3创建表,跟上面的sqlite3一样
CREATE TABLE `userinfo` (`uid` INT(10) NOT NULL AUTO_INCREMENT,`username` VARCHAR(64) NULL DEFAULT NULL,`departname` VARCHAR(64) NULL DEFAULT NULL,`created` DATE NULL DEFAULT NULL,PRIMARY KEY (`uid`)
);CREATE TABLE `userdetail` (`uid` INT(10) NOT NULL DEFAULT '0',`intro` TEXT NULL,`profile` TEXT NULL,PRIMARY KEY (`uid`)
)
创建表成功
3.4代码与sqlite3基本一样,还真有个别地方不一样
package mainimport ("database/sql""fmt"//"time"_ "github.com/go-sql-driver/mysql"
)func checkErr(err error) {if err != nil {panic(err)}
}func main() {db, err := sql.Open("mysql", "root:root123456@/mytest?charset=utf8")checkErr(err)//插入数据stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")checkErr(err)res, err := stmt.Exec("tom", "研发部门", "2023-1-09")checkErr(err)id, err := res.LastInsertId()checkErr(err)fmt.Println(id)//更新数据stmt, err = db.Prepare("update userinfo set username=? where uid=?")checkErr(err)res, err = stmt.Exec("astaxieupdate", id)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 intvar username stringvar department stringvar created stringerr = 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=?")checkErr(err)res, err = stmt.Exec(id)checkErr(err)affect, err = res.RowsAffected()checkErr(err)fmt.Println(affect)db.Close()
}
3.5验证数据
4.PostgreSQL
4.1数据库下载地址,我下载的zip压缩包
postgresql-14.8-2-windows-x64-binaries.zip
https://www.enterprisedb.com/download-postgresql-binaries
PostgreSQL 官网下载地址:https://www.postgresql.org/download/
4.2初始化数据库
命令行移动到解压后目录,初始化数据库:
bin\initdb -D data -U postgres -A password -E utf8 --locale=C -W
bin\initdb -D data -U postgres -A password -E utf8 --locale=C -W
命令行参数意义:
-D data 指定初始化的数据库目录(此处为当前目录的data文件夹)
-U postgres 数据库超级用户名(此处为postgres,如果不设置,会用当前windows用户名为账号)
-A password 数据库使用密码授权
-E utf8 数据库编码格式
--locale=C 数据库簇使用的本地化语言
-W 命令行执行后 输入密码
其他参数的 initdb --help查看
4.3启动数据库服务
初始化数据库完成后,指定数据库目录,启动数据库服务器:
bin\pg_ctl -D data start
运行命令行;
bin\pg_ctl -D data start
4.4验证登录数据库
4.5生成数据库表
检查表格信息,生成成功
4.6golang代码【重点--把下面代码中的删除数据的地方先注释】
上面的sqlite3,mysql都是一样的把代码中的删除注释,否则数据库中没有数据
//删除数据//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()
package mainimport ("database/sql""fmt"_ "github.com/lib/pq"
)func checkErr(err error) {if err != nil {panic(err)}
}func main() {db, err := sql.Open("postgres", "user=postgres password=password dbname=postgres 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)var lastInsertId interr = db.QueryRow("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) returning uid;", "astaxie", "研发部门", "2012-12-09").Scan(&lastInsertId)checkErr(err)fmt.Println("最后插入id =", lastInsertId)//更新数据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 intvar username stringvar department stringvar created stringerr = 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()
}
golang的运行打印信息
4.7验证数据,去数据库中验证数据
4.8总结
我们经常使用的数据库,sqlite3,mysql,postgrep基本满足需求了
五、测试环境的更改,docker的使用;
5.1docker常用命令;
在我的另外一个文章里,已经写好了,就是不在这里说了,感兴趣的可以看下docker的介绍
https://blog.csdn.net/wtt234/article/details/131674586
5.2.以mysql为例进行演示
跟上面一样,创建表以及运行golang代码,同上
重点看下5.1中关于msyql的部分在docker中的使用,后续实验环境可以考虑docker为主。
5.3下面的截图都是用navicat访问docker中的mysql镜像中的mysql==navicat中内容
在navicat中创建表
CREATE TABLE `userinfo` (`uid` INT(10) NOT NULL AUTO_INCREMENT,`username` VARCHAR(64) NULL DEFAULT NULL,`departname` VARCHAR(64) NULL DEFAULT NULL,`created` DATE NULL DEFAULT NULL,PRIMARY KEY (`uid`)
);CREATE TABLE `userdetail` (`uid` INT(10) NOT NULL DEFAULT '0',`intro` TEXT NULL,`profile` TEXT NULL,PRIMARY KEY (`uid`)
)
创建表成功
5.4===docker中内容===========验证在docker中mysql是否有数据==========================
在docker中验证下,是否新建了mytest数据库,数据库存在
在dicker中是否创建了表 表存在
mysql> use mytest; #使用数据库
mysql> show tables; #数据库下都是有哪些表
5.5golang代码运行
修改数据库连接信息
db, err := sql.Open("mysql", "test:123456@tcp(192.168.46.128:3306)/mytest?charset=utf8mb4")
所有代码:
package mainimport ("database/sql""fmt"//"time"_ "github.com/go-sql-driver/mysql"
)func checkErr(err error) {if err != nil {panic(err)}
}func main() {//db, err := sql.Open("mysql", "root:R1234567890@/mytest?charset=utf8mb4")//db, err := sql.Open("mysql", "root:root123456@tcp(127.0.0.1:3306)/mytest?charset=utf8mb4")db, err := sql.Open("mysql", "test:123456@tcp(127.0.0.1:3306)/mytest?charset=utf8mb4")checkErr(err)//插入数据stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")checkErr(err)res, err := stmt.Exec("tom", "研发部门", "2023-1-09")checkErr(err)id, err := res.LastInsertId()checkErr(err)fmt.Println(id)//更新数据stmt, err = db.Prepare("update userinfo set username=? where uid=?")checkErr(err)res, err = stmt.Exec("astaxieupdate", id)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 intvar username stringvar department stringvar created stringerr = 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=?")//checkErr(err)//res, err = stmt.Exec(id)//checkErr(err)//affect, err = res.RowsAffected()//checkErr(err)//fmt.Println(affect)//db.Close()
}
5.7验证结果
golang的中显示的运行结果
5.8显示结果
5.8.1navacat 中显示结果
5.8.2docker中数据库显示的信息
5.9docker运行验证环境测试效果不错,满足测试。