驱动
连接数据库是典型的CS架构,服务器端被动等待客户端建立TCP连接,并在此连接上进行特定的应用层协议。但一般用户并不需要了解这些细节,这些都被打包到驱动库中,只需要简单的调用打开就可以执行协议连接到指定的数据库。
数据库的种类和产品很多,协议也很多,Go官方很难提供针对不同数据库的驱动程序,往往由各个数据库官方或第三方给出不同的开发语言驱动库。但是,为了Go语言可以提前定义操作一个数据库的所有行为(接口)和数据(结构体)的规范,这些定义在database/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
源码中驱动注册:
func init() {
sql.Register("mysql", &MySQLDriver{})
}
连接
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql" //安装驱动和导入
)
var db *sql.DB
//db类型是*sql.DB,是一个操作数据库的句柄,底层是一个多协程安全的连接池
func init() {
var err error
db, err = sql.Open("mysql", "my_root:123@tcp(192.168.131.12:3306)/test")
//不能使用短格式定义,需要外init函数外部使用
if err != nil {
log.Fatal(err)
}
db.SetConnMaxLifetime(time.Second * 30) //超时时间
db.SetConnMaxIdleTime(time.Minute * 5) //最大空闲时间
db.SetMaxOpenConns(0) //最大链接数,0表示不限制
}
func main() {
err := db.Ping()
fmt.Println(err)
}
操作
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func init() {
var err error
db, err = sql.Open("mysql", "my_root:123@tcp(192.168.131.12:3306)/world")
if err != nil {
log.Fatal(err)
}
db.SetConnMaxLifetime(time.Second * 30)
db.SetMaxOpenConns(0)
db.SetMaxIdleConns(10)
}
//MySQL表结构
/*
mysql> desc city;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| CountryCode | char(3) | NO | MUL | | |
| District | char(20) | NO | | | |
| Population | int(11) | NO | | 0 | |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
*/
type City struct { //和字段对应的变量或结构以定义,最好和数据库中的字段顺序对应
Id int8
Name string
CountryCode string
District string
Population int
Cdate string
}
func main() {
//单行查询
// var city City
// city := City{}
city := new(City)
fmt.Println(city)
row := db.QueryRow("select * from city where id =?", 10)
if row.Err() != nil { //如果有错误,则调用error接口返回Error()string错误
log.Fatal(row.Err().Error())
}
err := row.Scan(&city.Id, &city.Name, &city.CountryCode, &city.District, &city.Population, &city.Cdate)
if err != nil {
log.Fatal(err)
}
fmt.Println(city)
fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
// 批量查询,预编译
stmt, err := db.Prepare("select * from city where id <?")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
rows, err := stmt.Query(20)
if err != nil {
log.Fatal(err)
}
for rows.Next() { //遍历,每一次遍历rows,内部指向当前行
err := rows.Scan(&city.Id, &city.Name, &city.CountryCode, &city.District, &city.Population, &city.Cdate)
if err != nil {
log.Fatal(err)
}
fmt.Println(city)
fmt.Printf("%T %v ", city.Cdate, city.Cdate)
t, err := time.Parse("2006-01-02 15:04:05", city.Cdate)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%T %v\n", t, t)
}
}
标签:city,err,数据库,mysql,db,Golang,标准,sql
From: https://blog.51cto.com/u_14218719/7266056