🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 1\. 下载依赖 ~~~ go get -u github.com/go-sql-driver/mysql ~~~ ## 2\. 使用Mysql驱动 ~~~ func Open(driverName, dataSourceName string) (*DB, error) ~~~ Open方法打开一个指定的数据库 driverName为驱动名称,例mysql dataSourceName为数据库连接信息 返回DB 和 error demo1 ~~~ func main() { // dsn: Data Source Name // 用户名为root,密码为123456,数据库为test dsn := "root:123456@tcp(127.0.0.1:3306)/test"        // Open()方法对dsn的一个格式校验,并没有实际连接到数据库 db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } defer db.Close() } ~~~ ### **Mysql Demo:** ~~~ // 定义一个全局变量 var db *sql.DB ​ // 定义初始化mysql的方法 func initMysql() (err error) { // dsn: Data Source Name // 用户名为root,密码为123456,数据库为test dsn := "root:123456@tcp(127.0.0.1:3306)/test" ​ // Open()方法对dsn的一个格式校验,并没有实际连接到数据库 db, err = sql.Open("mysql", dsn) if err != nil { panic(err) } ​ // 与数据库建立连接 err = db.Ping() if err != nil { fmt.Printf("connect to db failed, err:%v\n", err) return } return } ​ func main() { if err := initMysql(); err != nil { panic(err) } defer db.Close() fmt.Println("connected to db...") } ~~~ ## 3\. 单行查询 单行查询`db.QueryRow()`执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。 ~~~ func (db *DB) QueryRow(query string, args ...interface{}) *Row ~~~ 代码示例: ~~~ // 单行查询 func queryRowDemo() { // sql语句 sqlStr := "select id, name, age from user where id=?" var u user err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.name, &u.age) if err != nil { fmt.Printf("scan failed, err:%v\n", err) return } fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age) } ~~~ ## 4\. 多行查询 多行查询`db.Query()`执行一次查询,返回多行结果(即Rows),一般用于执行select命令。参数args表示query中的占位参数。 ~~~ func (db *DB) Query(query string, args ...interface{}) (*Rows, error) ~~~ 代码示例: ~~~ // 多行查询 func queryMultiRowDemo() { sqlStr := "select id, name, age from user where id > ?" rows, err := db.Query(sqlStr, 0) if err != nil { fmt.Printf("query failed, err:%v\n", err) return } // 关闭rows释放持有的数据库链接 defer rows.Close() ​ // 循环读取结果集中的数据 for rows.Next() { var u user err := rows.Scan(&u.id, &u.name, &u.age) if err != nil { fmt.Printf("scan failed, err:%v\n", err) return } fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age) } } ~~~ ## 5\. 插入数据 插入、更新和删除操作都使用`Exec`方法。 ~~~ func (db *DB) Exec(query string, args ...interface{}) (Result, error) ~~~ Exec执行一次命令(包括查询、删除、更新、插入等),返回的Result是对已执行的SQL命令的总结。参数args表示query中的占位参数。 代码示例: ~~~ // 插入数据 func insertRowDemo(name string, age int) { sqlStr := "insert into user(name, age) values (?,?)" result, err := db.Exec(sqlStr, name, age) if err != nil { fmt.Printf("insert failed, err:%v\n", err) return } // RowsAffected()方法,表示影响的行数 // num, err := result.RowsAffected() lastId, err := result.LastInsertId() // 新插入数据的id if err != nil { fmt.Printf("get lastinsert ID failed, err:%v\n", err) return } fmt.Printf("insert successfully, the id is %d.\n", lastId) } ~~~ ## 6\. 更新数据 ~~~ // 更新数据 func updateRowDemo() { sqlStr := "update user set age=? where id = ?" result, err := db.Exec(sqlStr, 23, 1) if err != nil { fmt.Printf("update data failed, err:%v\n", err) return } // 操作影响的行数 num, err := result.RowsAffected() if err != nil { fmt.Printf("get RowsAffected failed, err:%v\n", err) return } ​ fmt.Printf("update data successfully, %d rows affected\n", num) } ~~~ ## 7\. 删除数据 ~~~ // 删除数据 func deleteRowDemo() { sqlStr := "delete from user where id = ?" result, err := db.Exec(sqlStr, 3) if err != nil { fmt.Printf("delete failed, err:%v\n", err) return } num, err := result.RowsAffected() // 操作影响的行数 if err != nil { fmt.Printf("get RowsAffected failed, err:%v\n", err) return } fmt.Printf("delete success, affected rows:%d\n", num) } ~~~ ## 8\. Go实现Mysql预处理 为什么要预处理? 1. 优化MySQL服务器重复执行SQL的方法,可以提升服务器性能,提前让服务器编译,一次编译多次执行,节省后续编译的成本。 2. 避免SQL注入问题 `database/sql`中使用下面的`Prepare`方法来实现预处理操作。 ~~~ func (db *DB) Prepare(query string) (*Stmt, error) ~~~ ~~~ // 预处理 func prepareQueryDemo() { sqlStr := "select id, name, age from user where id > ?" stmt, err := db.Prepare(sqlStr) if err != nil { fmt.Printf("prepare failed, err:%v\n", err) return } defer stmt.Close() rows, err := stmt.Query(0) if err != nil { fmt.Printf("query failed, err:%v\n", err) return } defer rows.Close() // 循环读取结果集中的数据 for rows.Next() { var u user err := rows.Scan(&u.id, &u.name, &u.age) if err != nil { fmt.Printf("scan failed, err:%v\n", err) return } fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age) } } ~~~ ## 9\. Go实现Mysql事务 Go语言中使用以下三个方法实现MySQL中的事务操作。 开始事务 ~~~ func (db *DB) Begin() (*Tx, error) ~~~ 提交事务 ~~~ func (tx *Tx) Commit() error ~~~ 回滚事务 ~~~ func (tx *Tx) Rollback() error ~~~ 示例代码 ~~~ // 事务操作 func transactionDemo() { tx, err := db.Begin() // 开启事务 if err != nil { if tx != nil { tx.Rollback() // 回滚 } fmt.Printf("begin trans failed, err:%v\n", err) return } sqlStr1 := "update user set age=30 where id=?" result1, err := tx.Exec(sqlStr1, 1) if err != nil { tx.Rollback() // 回滚 fmt.Printf("exec sql failed, err:%v\n", err) return } num1, err := result1.RowsAffected() if err != nil { tx.Rollback() // 回滚 fmt.Printf("exec result.RowsAffected failed, err:%v\n", err) return } ​ sqlStr2 := "update user set age=30 where id=?" result2, err := tx.Exec(sqlStr2, 2) if err != nil { tx.Rollback() // 回滚 fmt.Printf("exec sql failed, err:%v\n", err) return } num2, err := result2.RowsAffected() if err != nil { tx.Rollback() // 回滚 fmt.Printf("exec result.RowsAffected failed, err:%v\n", err) return } ​ fmt.Println(num1, num2) if num1 == 1 && num2 == 1 { fmt.Println("事务提交啦。。。") tx.Commit() } else { tx.Rollback() fmt.Println("事务回滚啦。。。") } fmt.Println("exec trans success!") } ~~~