Golang 数据库标准开发
数据库标准开发
驱动
连接数据库是典型的CS变成,服务器端被动等待客户端建立TCP连接,并在此连接上进行特定的应用层协议。但是一般用户并不需要了解这些细节,这些都被打包到了驱动库中,只需要简单的调用打开就可以指定协议连接到指定的数据库中
数据库的种类和产品太多,协议太多,Go官方很难提供针对不同数据库的驱动程序,往往由各数据库官方或第三方给出不同开发语言的驱动库。但是,为了Go语言可以提前定义操作一个数据库的所有行为(接口)和数据(结构体)的规范,这些定义在databasq/sql下。
mysql驱动:
- https://github.com/go-sql-driver/mysql 支持database/sql,推荐
- https://github.com/ziutek/mymysql 支持database/sql,支持自定义接口
- https://github.com/Philio/GoMySQL 不支持database/sql,支持自定义接口
安装mysql的驱动
$ go get -u github.com/go-sql-driver/mysql
导入
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
注册驱动
// github.com/go-sql-driver/mysql/mysql/driver.go 代码中有注册驱动
func init() { // 83 行
sql.Register("mysql", &MySQLDriver{})
}
连接
DSN 例子 :https://github.com/go-sql-driver/mysql#Examples
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
username:password@protocol(address)/dbname?param=value
connstr := "root:123456@tcp(127.0.0.1:3306)/test"
connstr := "root:123456@tcp/test"
connstr := "root:123456@/test"
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"time"
)
var db *sql.DB
func init() {
connect := "root:123456@tcp(127.0.0.1:3306)/test"
var err error
db, err = sql.Open("mysql", connect)
if err != nil {
fmt.Println(err)
}
db.SetConnMaxLifetime(time.Second * 30) //最大连接存活时间
db.SetMaxOpenConns(10) // 最大连接数
db.SetMaxIdleConns(10) // 最大闲置连接
}
func main() {
fmt.Println(db)
}
db类型是*sql.DB, 是一个操作数据库的句柄,底层是一个多协程安全的连接池。
操作
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"time"
)
var db *sql.DB
func init() {
connect := "root:123456@tcp(127.0.0.1:3306)/test"
var err error
db, err = sql.Open("mysql", connect)
if err != nil {
fmt.Println(err)
}
db.SetConnMaxLifetime(time.Second * 30) //最大连接存活时间
db.SetMaxOpenConns(10) // 最大连接数
db.SetMaxIdleConns(10) // 最大闲置连接
}
type Emp struct {
emp_no int
birth_date string
first_name string
last_name string
gender int
hire_date string
}
func main() {
//fmt.Println(db)
var e Emp
row := db.QueryRow("select * from employees where emp_no = 10013")
fmt.Println(row)
err := row.Scan(&e.emp_no, &e.birth_date, &e.first_name, &e.last_name, &e.gender, &e.hire_date)
if err != nil {
log.Panic(err)
}
fmt.Println(e)
fmt.Println("~~~~~~~~~~~~~~~~~~~~")
rows, err := db.Query("select * from employees where emp_no > ?", 10017)
if err != nil {
log.Panic(err)
}
for rows.Next() {
var e Emp
err := rows.Scan(&e.emp_no, &e.birth_date, &e.first_name, &e.last_name, &e.gender, &e.hire_date)
if err != nil {
log.Panic(err)
}
fmt.Println(e)
}
}
- 驱动安装和导入,例如
import _ "github.com/go-sql-driver/mysql"
- 连接数据库并返回数据库操作句柄,例如
sql.Open("mysql","dujie:123456@tcp(localhost:3306)/test")
- 使用db提供的接口函数
- 使用db.Prepare预编译并使用参数化查询
- 对预编译的SQL语句进行缓存,省去了每次解析优化该SQL语句的过程
- 防止注入攻击
- 使用返回的sql.Stmt操作数据库
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"time"
)
var db *sql.DB
func init() {
connect := "root:123456@tcp(127.0.0.1:3306)/test"
var err error
db, err = sql.Open("mysql", connect)
if err != nil {
fmt.Println(err)
}
db.SetConnMaxLifetime(time.Second * 30) //最大连接存活时间
db.SetMaxOpenConns(10) // 最大连接数
db.SetMaxIdleConns(10) // 最大闲置连接
}
type Emp struct {
emp_no int
birth_date string
first_name string
last_name string
gender int
hire_date string
}
func main() {
//fmt.Println(db)
var e Emp
row := db.QueryRow("select * from employees where emp_no = 10013")
fmt.Println(row)
err := row.Scan(&e.emp_no, &e.birth_date, &e.first_name, &e.last_name, &e.gender, &e.hire_date)
if err != nil {
log.Panic(err)
}
fmt.Println(e)
fmt.Println("~~~~~~~~~~~~~~~~~~~~")
stmt, _ := db.Prepare("select * from employees where emp_no > ?")
rows, err := stmt.Query(10017)
if err != nil {
fmt.Println(err)
}
for rows.Next() {
var e Emp
rows.Scan(&e.emp_no, &e.birth_date, &e.first_name, &e.last_name, &e.gender, &e.hire_date)
fmt.Println(e)
}
}
插入、修改、删除
增删改其实操作都一样,都是通过exec来控制
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"time"
)
var db *sql.DB
func init() {
connect := "root:123456@tcp(127.0.0.1:3306)/test"
var err error
db, err = sql.Open("mysql", connect)
if err != nil {
fmt.Println(err)
}
db.SetConnMaxLifetime(time.Second * 30) //最大连接存活时间
db.SetMaxOpenConns(10) // 最大连接数
db.SetMaxIdleConns(10) // 最大闲置连接
}
type Emp struct {
emp_no int
birth_date string
first_name string
last_name string
gender int
hire_date string
}
func main() {
// 增加
//var e Emp
result, err := db.Exec("insert into employees(emp_no,birth_date,first_name,last_name,gender,hire_date) values(10023,'1980-01-01','John','tom',1,'2006-01-02')")
if err != nil {
log.Panicln(err)
}
fmt.Println(result)
// 删除
stmt, errs := db.Prepare("delete from titles where emp_no=?")
fmt.Println(errs)
if errs != nil {
fmt.Println(errs)
}
result, errd := stmt.Exec(10016)
if errd != nil {
log.Fatalln(errd)
}
fmt.Println(result)
// 修改
result, erra := db.Exec("update titles set title = ? where emp_no=?", "dujie", 10014)
if erra != nil {
log.Fatal(erra)
}
fmt.Println(result)
}
http://dycloud.fun/2023/05/03/Golang%E6%95%B0%E6%8D%AE%E5%BA%93%E6%A0%87%E5%87%86%E5%BC%80%E5%8F%91/
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 J.のblog!
评论