下载依赖
go get -u github.com/go-sql-driver/mysql
使用MySQL驱动
func Open(driverName, dataSourceName string) (*DB, error)
Open打开一个dirverName指定的数据库,dataSourceName指定数据源,一般至少包括数据库文件名和其它连接必要的信息。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
dsn := "mysql:password@tcp(127.0.0.1:3306)/boor"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
}
为什么上面代码中的defer db.Close()语句不应该写在if err != nil的前面呢
初始化连接
Open函数可能只是验证其参数格式是否正确,实际上并不创建与数据库的连接。如果要检查数据源的名称是否真实有效,应该调用Ping方法。
返回的DB对象可以安全地被多个goroutine并发使用,并且维护其自己的空闲连接池。因此,Open函数应该仅被调用一次,很少需要关闭这个DB对象。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func main() {
dsn := "root:123456@tcp(127.0.0.1:3306)/door?charset=utf8mb4&parseTime=True"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println(err)
return
}
err = db.Ping()
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
}
其中sql.DB是表示连接的数据库对象(结构体实例),它保存了连接数据库相关的所有信息。它内部维护着一个具有零到多个底层连接的连接池,它可以安全地被多个goroutine同时使用。
SetMaxOpenConns
func (db *DB) SetMaxOpenConns(n int)
SetMaxOpenConns设置与数据库建立连接的最大数目。 如果n大于0且小于最大闲置连接数,会将最大闲置连接数减小到匹配最大开启连接数的限制。 如果n<=0,不会限制最大开启连接数,默认为0(无限制)。
SetMaxIdleConns
func (db *DB) SetMaxIdleConns(n int)
SetMaxIdleConns设置连接池中的最大闲置连接数。 如果n大于最大开启连接数,则新的最大闲置连接数会减小到匹配最大开启连接数的限制。 如果n<=0,不会保留闲置连接。
查询
单行查询db.QueryRow()执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。(如:未找到结果)
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
type user struct {
id int
name string
}
func selct(db *sql.DB) (users *user, err error) {
u := user{}
sqlStr := "select id,username from doorindex_username "
err = db.QueryRow(sqlStr).Scan(&u.id, &u.name)
if err != nil {
return nil, err
}
return &u, nil
}
func main() {
var db *sql.DB
dsn := "root:123456@tcp(127.0.0.1:3306)/door?charset=utf8mb4&parseTime=True"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println(err)
return
}
err = db.Ping()
if err != nil {
fmt.Println(err)
return
}
u, err := selct(db)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%T,%v\n", u.id, u.id)
fmt.Printf("%T,%v\n", u.name, u.name)
defer db.Close()
}
多行查询
多行查询db.Query()执行一次查询,返回多行结果(即Rows),一般用于执行select命令。参数args表示query中的占位参数。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
type user struct {
id int
name string
}
func selct(db *sql.DB) (users *sql.Rows, err error) {
sqlStr := "select id,username from doorindex_username"
rows, err := db.Query(sqlStr)
if err != nil {
return nil, err
}
return rows, nil
}
func main() {
var u user
var db *sql.DB
dsn := "root:123456@tcp(127.0.0.1:3306)/door?charset=utf8mb4&parseTime=True"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println(err)
return
}
err = db.Ping()
if err != nil {
fmt.Println(err)
return
}
rows, err := selct(db)
if err != nil {
fmt.Println(err, "rows")
}
for rows.Next() {
err := rows.Scan(&u.id, &u.name)
if err != nil {
fmt.Println(err, "scan")
}
}
fmt.Println(u.id, u.name, "user")
defer rows.Close()
defer db.Close()
}
插入数据
插入、更新和删除操作都使用Exec方法。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
Exec执行一次命令(包括查询、删除、更新、插入等),返回的Result是对已执行的SQL命令的总结。参数args表示query中的占位参数。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
type user struct {
id int
name string
}
func selct(db *sql.DB) (users sql.Result, err error) {
sqlStr := "INSERT INTO doorindex_username(id,username,jurisdiction) VALUE (?,?,?)"
resu, err := db.Exec(sqlStr, 3, "13555202017", 0)
if err != nil {
return nil, err
}
return resu, nil
}
func main() {
var db *sql.DB
dsn := "root:123456@tcp(127.0.0.1:3306)/door?charset=utf8mb4&parseTime=True"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println(err)
return
}
err = db.Ping()
if err != nil {
fmt.Println(err)
return
}
//获取sql.Result
resu, err := selct(db)
if err != nil {
fmt.Println(err, "rows")
}
//执行保存,v是执行后的状态
v, ok := resu.LastInsertId()
fmt.Println(ok)
fmt.Println(v)
defer db.Close()
}
修改操作
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
type user struct {
id int
name string
}
func selct(db *sql.DB) (users sql.Result, err error) {
sqlStr := "UPDATE doorindex_username set username=? where id=?"
resu, err := db.Exec(sqlStr, "123456789", 3)
if err != nil {
return nil, err
}
return resu, nil
}
func main() {
var db *sql.DB
dsn := "root:123456@tcp(127.0.0.1:3306)/door?charset=utf8mb4&parseTime=True"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println(err)
return
}
err = db.Ping()
if err != nil {
fmt.Println(err)
return
}
resu, err := selct(db)
if err != nil {
fmt.Println(err, "rows")
}
//执行修改操作,v是执行的状态
v, ok := resu.RowsAffected()
fmt.Println(ok)
fmt.Println(v)
defer db.Close()
}
执行删除操作
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func selct(db *sql.DB) (users sql.Result, err error) {
sqlStr := "DELETE FROM doorindex_username where id=?"
resu, err := db.Exec(sqlStr, 3)
if err != nil {
return nil, err
}
return resu, nil
}
func main() {
var db *sql.DB
dsn := "root:123456@tcp(127.0.0.1:3306)/door?charset=utf8mb4&parseTime=True"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println(err)
return
}
err = db.Ping()
if err != nil {
fmt.Println(err)
return
}
resu, err := selct(db)
if err != nil {
fmt.Println(err, "rows")
}
//执行删除操作,v是执行的状态
v, ok := resu.RowsAffected()
fmt.Println(ok)
fmt.Println(v)
defer db.Close()
}