1. 准备表
创建数据库
1
| create database go_db DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
|
创建表
1 2 3 4 5
| CREATE TABLE user_tb1( id INTEGER PRIMARY KEY AUTO_INCREMENT, username VARCHAR(20), `password` VARCHAR(20) )
|
添加数据
1 2
| INSERT INTO user_tb1(username,password) VALUES("tom", "123"); INSERT INTO user_tb1(username,password) VALUES("kite", "456");
|
2. 安装驱动
1
| go get -u github.com/go-sql-driver/mysql
|
初始化模块
更新依赖
3. 获取连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package main
import ( "database/sql" "time"
_ "github.com/go-sql-driver/mysql" )
func main() { db, err := sql.Open("mysql", "ops:xxx.@/go_db") if err != nil { panic(err) } db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) }
|
初始化连接
Open函数可能只是验证其参数格式是否正确,实际上并不创建与数据库的连接。如果要检查数据源的名称是否真实有效。应该调用ping方法。
返回的DB对象可以安全的被多个goroutine并发使用,并且维护其自己的空闲连接池。因此,Open函数应该仅被调用一次,很少需要关闭这个DB对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package main
import ( "database/sql" "fmt" "log"
_ "github.com/go-sql-driver/mysql" )
var db *sql.DB
func initDB() error { var err error db, err = sql.Open("mysql", "ops:xxx.@tcp(192.168.10.10:3306)/go_db?charset=utf8mb4&parseTime=True") if err != nil { return err } db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) err2 := db.Ping() if err2 != nil { return err2 } return nil }
func main() { err := initDB() if err != nil { log.Fatal(err) } fmt.Println("初始化成功") }
|
4. 插入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package main
import ( "database/sql" "fmt" "log" "time"
_ "github.com/go-sql-driver/mysql" )
var db *sql.DB
func initDB() error { var err error db, err = sql.Open("mysql", "ops:xxx.@tcp(192.168.10.10:3306)/go_db?charset=utf8mb4&parseTime=True") if err != nil { return err } db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) err2 := db.Ping() if err2 != nil { return err2 } return nil }
func insertData() { sqlStr := "insert into user_tb1(username,password) values(?,?)" ret, err := db.Exec(sqlStr, "张三", "zs123") if err != nil { log.Printf("insert failed, err: %v\n", err) return } theID, err2 := ret.LastInsertId() if err2 != nil { log.Printf("get lastinsert ID failed, err:%v\n", err) return } fmt.Printf("theID: %v\n", theID) }
func main() { err := initDB() if err != nil { log.Fatal(err) } else { fmt.Println("初始化成功") }
insertData() }
|
5. 查询操作
单行查询db.QueryRow()
执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回的Scan方法被调用时,才会返回被延迟的错误。
5.1 定义一个结构体
1 2 3 4 5
| type user struct { id int username string password string }
|
5.2 单行查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| package main
import ( "database/sql" "fmt" "log" "time"
_ "github.com/go-sql-driver/mysql" )
var db *sql.DB
type user struct { id int username string password string }
func initDB() error { var err error db, err = sql.Open("mysql", "ops:xxx.@tcp(192.168.10.10:3306)/go_db?charset=utf8mb4&parseTime=True") if err != nil { return err } db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) err2 := db.Ping() if err2 != nil { return err2 } return nil }
func queryRowDemo() user { sqlStr := "select id,username,password from user_tb1 where id=?" var u user err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.username, &u.password) if err != nil { log.Printf("%v\n", err) } return u } func main() { err := initDB() if err != nil { log.Fatal(err) } else { fmt.Println("初始化成功") }
ret := queryRowDemo() fmt.Printf("ret: %v\n", ret) }
|
执行结果:
初始化成功
ret: {1 tom 123}
5.3 多行查询
多行查询db.Query()
执行一次查询,返回多行结果(即Rows),一般用于执行select命令,参数args表示query中的展位参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| package main
import ( "database/sql" "fmt" "log" "time"
_ "github.com/go-sql-driver/mysql" )
var db *sql.DB
type user struct { id int username string password string }
func initDB() error { var err error db, err = sql.Open("mysql", "ops:xxx.@tcp(192.168.10.10:3306)/go_db?charset=utf8mb4&parseTime=True") if err != nil { return err } db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) err2 := db.Ping() if err2 != nil { return err2 } return nil }
func queryRowDemo(id int) []user { sqlStr := "select id,username,password from user_tb1 where id>?" rows, err := db.Query(sqlStr, id) if err != nil { log.Printf("%v\n", err) } defer rows.Close()
var u user ret := make([]user, 0) for rows.Next() { err2 := rows.Scan(&u.id, &u.username, &u.password) if err2 != nil { log.Printf("scan failed, err:%v\n", err2) } ret = append(ret, u) } return ret } func main() { err := initDB() if err != nil { log.Fatal(err) } else { fmt.Println("初始化成功") }
ret := queryRowDemo(1) fmt.Printf("ret: %v\n", ret) }
|
运行结果:
初始化成功
ret: [{2 kite 456} {3 张三 zs123}]
5.4 更新操作
插入、更新和删除操作都是使用Exec
方法
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| package main
import ( "database/sql" "fmt" "log" "time"
_ "github.com/go-sql-driver/mysql" )
var db *sql.DB
type user struct { id int username string password string }
func initDB() error { var err error db, err = sql.Open("mysql", "ops:xxx.@tcp(192.168.10.10:3306)/go_db?charset=utf8mb4&parseTime=True") if err != nil { return err } db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) err2 := db.Ping() if err2 != nil { return err2 } return nil }
func updateData() { sql := "update user_tb1 set username=?,password=? where id=?" ret, err := db.Exec(sql, "kite2", "Kite123", "2") if err != nil { log.Printf("%v\n", err) } rows, err2 := ret.RowsAffected() if err2 != nil { log.Println("更新失败", err2) } fmt.Printf("更新成功,更新行数: %v\n", rows) } func main() { err := initDB() if err != nil { log.Fatal(err) } else { fmt.Println("初始化成功") } updateData() }
|
运行结果:
初始化成功
更新成功,更新行数: 1
5.5 删除操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| package main
import ( "database/sql" "fmt" "log" "time"
_ "github.com/go-sql-driver/mysql" )
var db *sql.DB
type user struct { id int username string password string }
func initDB() error { var err error db, err = sql.Open("mysql", "ops:xxx.@tcp(192.168.10.10:3306)/go_db?charset=utf8mb4&parseTime=True") if err != nil { return err } db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) err2 := db.Ping() if err2 != nil { return err2 } return nil }
func delData() { sql := "delete from user_tb1 where id=?" r, err := db.Exec(sql, "1") if err != nil { log.Printf("%v\n", err) return } rows, err2 := r.RowsAffected() if err2 != nil { log.Printf("删除行失败,%v\n", err2) return } fmt.Printf("删除成功,删除的行数: %v\n", rows) } func main() { err := initDB() if err != nil { log.Fatal(err) } else { fmt.Println("初始化成功") } delData() }
|
运行结果:
初始化成功
删除成功,删除的行数: 1