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() error
Begin() (Tx, error)
}
1.4driver.Stmt
type Stmt interface {
Close() error
NumInput() int
Exec(args []Value) (Result, error)
Query(args []Value) (Rows, error)
}
1.5driver.Tx
type Tx interface {
Commit() error
Rollback() error
}
1.6driver.Result
type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
}
1.7driver.Rows
type Rows interface {
Columns() []string
Close() error
Next(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 main
import (
"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 int
var username string
var department string
var created time.Time
err = 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 main
import (
"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 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=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}