初始化创建数据库连接
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/go_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
return nil
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
}
输出结果
如果连接创建成功的话不会有输出内容,
其中sql.DB是表示连接的数据库对象(结构体实例),它保存了连接数据库相关的所有信息。它内部维护着一个具有零到多个底层连接的连接池,它可以安全地被多个goroutine同时使
设置数据库最大连接数和数据库最大闲置连接数,试了一下,貌似没啥用.(可能是我尝试的方法不对.)
package main
import (
"database/sql"
"fmt"
_ "/go-sql-driver/mysql"
)
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/go_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
}
数据库查询操作
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct {
id int
age int
name string
}
func queryRowDemo() {
sqlStr := "select id ,name ,age from user where name = ? "
var u user
err := db.QueryRow(sqlStr, "monkey").Scan(&u.id, &, &u.age) //这里quaryrow中传入的数字就表示上面指定的sql语句中的多少行.指定啥条件就进行啥条件的查询.
//例如指定name条件,那么就填写name字段,指定id条件,就填写id条件字段.
if err != nil {
fmt.Printf("scan failed ,err:%v\n", err)
return
}
fmt.Printf("id:%d,name:%s,age:%d\n", u.id, , u.age)
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
queryRowDemo()
}
说明一下
这里的步骤如下:
1.首先初始化数据库连接,确保数据库连接正常.
2.创建查询语句函数.
3.main函数中调用查询语句函数.
多行查询
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct { //根据数据库中的字段内容创建一个相同字段的结构体
id int
age int
name string
}
func queryMulitRowDemo() {
sqlStr := "select id ,name ,age from user where id >= ? and id <=? "
rows, err := db.Query(sqlStr, 0, 3) //这里指定的是大于多少行,和小于等于多少行,这里输入的args内容对应的是sql语句中?问号的位置代表的内容.
if err != nil {
fmt.Printf("query failed err : %v\n", err)
return
}
defer rows.Close()
var u user
for rows.Next() {
err := rows.Scan(&u.id, &, &u.age) //这里表示的是查询出来的字段与结构体中的字段进行关联
if err != nil {
fmt.Printf("scan failed ,err:%v\n", err)
return
}
fmt.Printf("id:%d,name:%v,age:%d\n", u.id, , u.age) //这里进行打印操作
}
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
//queryRowDemo()
queryMulitRowDemo() //批量查询数据
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\11databases>11databases.exe
id:1,name:jack,age:18
id:2,name:monkey,age:11
id:3,name:zhangsan,age:22
数据插入
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct { //根据数据库中的字段内容创建一个相同字段的结构体
id int
age int
name string
}
//主函数
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
//queryRowDemo() //单条数据查询
//queryMulitRowDemo() //批量查询数据
insertRowDemo("老王", 33)
}
//插入数据
func insertRowDemo(inStr string, inAge int) {
sqlStr := "insert into user(name,age) value(?,?)" //这里有两个??问号,分辨代表name和age字段的值.
ret, err := db.Exec(sqlStr, inStr, inAge) //这里使用的是传参的方式将外部的参数传入到函数内部.进行数据插入.
// 如果不使用传参操作可以直接在对应位置设置指定类型的数值.(类型参考结构体中已经指定好的类型.
if err != nil {
fmt.Printf("insert failed err:%v", err)
return
}
theId, err := ret.LastInsertId() //新插入数据的id,可以在调用代码的过程中返回最新数值id,可以将内容写到日志中.
if err != nil {
fmt.Printf("get lastinsert ID failed ,err:%v\n", err)
}
fmt.Printf("insert success ,the id is %d.\n", theId)
}
输出结果
C:\Users\34826\AppData\Local\Temp\___go_build_main_go__2_.exe #gosetup
insert success ,the id is 4.
查询结果
MySQL [sql_test]> select id , name , age from user;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 1 | jack | 1 |
| 2 | monkey | 3 |
| 3 | zhangsan | 22 |
| 4 | 老王 | 33 |
+----+----------+------+
4 rows in set (0.00 sec)
更新数据
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct { //根据数据库中的字段内容创建一个相同字段的结构体
id int
age int
name string
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
//queryRowDemo() //单条数据查询
//queryMulitRowDemo() //批量查询数据
//insertRowDemo("老王", 33)
updateRowDemo(99, 1)
}
//更新数据
func updateRowDemo(upDate int, upDateID int) {
sqlStr := "update user set age=? where id = ?"
ret, err := db.Exec(sqlStr, upDate, upDateID)
if err != nil {
fmt.Printf("update failed err:%v\n", err)
return
}
n, err := ret.RowsAffected() //操作影响的行数
if err != nil {
fmt.Printf("get rows affected failed ,err:%v\n", err)
return
}
fmt.Printf("update success,affected rows:%d\n", n) //更新影响的行数.
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\11databases>11databases.exe
update success,affected rows:1
数据库查询结果
MySQL [sql_test]> select id,name,age from user;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 1 | jack | 99 |
| 2 | monkey | 3 |
| 3 | zhangsan | 22 |
| 4 | 老王 | 33 |
+----+----------+------+
4 rows in set (0.00 sec)
删除数据
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct { //根据数据库中的字段内容创建一个相同字段的结构体
id int
age int
name string
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
defer db.Close()
//queryRowDemo() //单条数据查询
//queryMulitRowDemo() //批量查询数据
//insertRowDemo("老王", 33)
//updateRowDemo(99, 1)
deleteRowDemo(10) //删除数据
}
//删除数据
func deleteRowDemo(deleteID int) {
sqlStr := "delete from user where id = ?"
ret, err := db.Exec(sqlStr, deleteID)
if err != nil {
fmt.Printf("delete failed err ,err :%v\n", err)
return
}
n, err := ret.RowsAffected() //返回影响的行数
if err != nil {
fmt.Printf("get RowsAffected failed,err:%v\n", err)
return
}
fmt.Printf("delete success ,affected row:%d\n", n)
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\11databases>11databases.exe
delete success ,affected row:0
数据库查询结果
MySQL [sql_test]> select id , name , age from user;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 2 | monkey | 3 |
| 3 | zhangsan | 22 |
| 4 | 老王 | 33 |
+----+----------+------+
3 rows in set (0.00 sec)
使用perpare进行sql语句的预处理
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct { //根据数据库中的字段内容创建一个相同字段的结构体
id int
age int
name string
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
defer db.Close()
//queryRowDemo() //单条数据查询
//queryMulitRowDemo() //批量查询数据
//insertRowDemo("老王", 33)
//updateRowDemo(99, 1)
//deleteRowDemo(10) //删除数据
perpareQueayDemo(1)
}
//查询操作的预处理
func perpareQueayDemo(queryID int) {
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(queryID)
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.age)
if err != nil {
fmt.Printf("scan failed,err:%v\n", err)
return
}
fmt.Printf("id:%d,name:%v,age:%d\n", u.id, , u.age)
}
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\11databases>11databases.exe
id:2,name:monkey,age:3
id:3,name:zhangsan,age:22
id:4,name:老王,age:33
插入操作的预处理
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct { //根据数据库中的字段内容创建一个相同字段的结构体
id int
age int
name string
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
defer db.Close()
//queryRowDemo() //单条数据查询
//queryMulitRowDemo() //批量查询数据
//insertRowDemo("老王", 33)
//updateRowDemo(99, 1)
//deleteRowDemo(10) //删除数据
//perpareQueayDemo(1)
perpareInsertDemo("大魔王", 12)
}
//插入操作预处理
func perpareInsertDemo(insertName string, insertAge int) {
sqlStr := "insert into user(name,age) values(?,?)"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("perpare failed ,err : %v\n", err)
return
}
defer stmt.Close()
ret, err := stmt.Exec(insertName, insertAge) //如果第一个接收者不需要进行定义的话那么可以直接使用=等号.不需要使用:= 声明赋值操作.
if err != nil {
fmt.Printf("insert failed err:%v\n", err)
return
}
n, err := ret.RowsAffected()
if err != nil {
fmt.Printf("get Rows Affected failed err:%v\n", err)
return
}
fmt.Printf("insert rows is %d\n", n)
fmt.Println("insert sussecc.")
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\11databases>11databases.exe
insert rows is 1
insert sussecc.
数据库查询结果
MySQL [sql_test]> select id , name , age from user;
+----+-----------+------+
| id | name | age |
+----+-----------+------+
| 2 | monkey | 3 |
| 3 | zhangsan | 22 |
| 4 | 老王 | 33 |
| 5 | 大魔王 | 12 |
| 6 | 大魔王 | 12 |
+----+-----------+------+
5 rows in set (0.00 sec)
更新perpare操作
var db *sql.DB //这里注意,要是用sql.DB的指针形式.
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //用户名==>密码==>连接方式==>地址==>端口号==>数据库名称
db, err = sql.Open("mysql", dsn) //根据预先定义的数据库连接参数创建数据库连接.
if err != nil {
return err
}
// 尝试与数据库建立连接(校验dsn是否正确)
err = db.Ping()
if err != nil {
return err
}
//db.SetMaxOpenConns(20) //一般跟数据库的配置文件内容一样.
//db.SetMaxIdleConns(10) //最大闲置连接数.如果n大于设置的闲置连接数
return nil
}
type user struct { //根据数据库中的字段内容创建一个相同字段的结构体
id int
age int
name string
}
func main() {
err := initDB() //数据库初始化
if err != nil {
fmt.Printf("init db failed ,err:%v\n", err)
return
}
defer db.Close()
//queryRowDemo() //单条数据查询
//queryMulitRowDemo() //批量查询数据
//insertRowDemo("老王", 33)
//updateRowDemo(99, 1)
//deleteRowDemo(10) //删除数据
//perpareQueayDemo(1)
//perpareInsertDemo("大魔王", 12)
perpareUpdateDemo("3魔王", 6)
}
//更新perpare操作
func perpareUpdateDemo(updateName string, updateID int) {
sqlStr := "update user set name=? where id =?" //定义原始sql
stmt, err := db.Prepare(sqlStr) //预编译SQL语句
if err != nil {
fmt.Printf("perpare failed err:%v\n", err)
return
}
defer stmt.Close()
ret, err := stmt.Exec(updateName, updateID)
if err != nil {
fmt.Printf("update failed err:%v\n", err)
return
}
n, err := ret.RowsAffected() //显示修改了多少行数据
if err != nil {
fmt.Printf("get rows failed err:%v\n", err)
return
}
fmt.Println("update rows is ", n)
}
输出结果
C:\Users\34826\AppData\Local\Temp\___go_build_main_go__2_.exe #gosetup
update rows is 1
数据库查询结果
MySQL [sql_test]> select id , name , age from user;
+----+-----------+------+
| id | name | age |
+----+-----------+------+
| 2 | monkey | 3 |
| 3 | zhangsan | 22 |
| 4 | 老王 | 33 |
| 5 | 大魔王 | 12 |
| 6 | 3魔王 | 12 |
+----+-----------+------+
5 rows in set (0.00 sec)
手动创建一个事务
package main
import (
"database/sql"
"fmt"
_ "/go-sql-driver/mysql"
)
var db *sql.DB
func initDB() (err error) {
dsn := "root:yaochizaocan@tcp(192.168.11.236:3306)/sql_test" //声明连接的相关信息
db, err = sql.Open("mysql", dsn) //声明数据库类型,并使用预先定义完成的参数进连接 关键问题,如果编译执行的时候出现panic的话很有可能是这里使用了:=进行赋值操作.
if err != nil {
return err
}
err = db.Ping() //测试数据库连接是否畅通
if err != nil {
return err
}
return nil
}
type user struct {
id int
name string
age int
}
//main函数
func main() {
err := initDB()
if err != nil {
fmt.Printf("数据库初始化失败,err:%v\n", err)
return
}
transactionDemo()
}
//创建一个事务
func transactionDemo() {
tx, err := db.Begin() //显示的开启一个事务
if err != nil {
if tx != nil {
tx.Rollback() //回滚
}
fmt.Printf("begin transaction failed ,err:%v\n", err)
return
}
sqlStr1 := "update user set age=30 where id = ?"
ret1, err := tx.Exec(sqlStr1, 2)
if err != nil {
tx.Rollback()
fmt.Printf("exec sql1 failed,err:%v\n", err)
return
}
affRow1, err := ret1.RowsAffected() //返回修改的行数成功的话aff1 会等于1
if err != nil {
tx.Rollback() //回滚
fmt.Printf("exec ret1 rowaffected failed err:%v\n", err)
return
}
sqlStr2 := "update user set age=40 where id = ?"
ret2, err := tx.Exec(sqlStr2, 3)
if err != nil {
tx.Rollback() //回滚
fmt.Println("事务回滚了.")
fmt.Printf("ret2 exec failed err : %v\n", err)
return
}
affRow2, err := ret2.RowsAffected() //执行行数 aff2 成功的话会等于1
if err != nil {
tx.Rollback() //回滚
fmt.Println("事务回滚了.")
fmt.Printf("exec ret2 affRow2 failed ,err :%v\n", err)
return
}
fmt.Println(affRow1, affRow2)
if affRow1 == 1 && affRow2 == 1 {
fmt.Println("事务提交了...")
tx.Commit() //显示的提交事务
} else {
tx.Rollback() //事务回滚...
fmt.Println("事务回滚了.")
}
fmt.Println("exec transcation sussecc!")
}
输出结果
D:\Go\Go\src\code.oldboy.com\studygolang\05lesson5\12shiwu>12shiwu.exe
1 1
事务提交了...
exec transcation sussecc!
说明一下
这里在进行编译的时候是没报错的,但是在编译完成进行执行的时候出现报错.报错内容是空指针引用错误.(panic: runtime error: invalid memory address or nil pointer dereference) ,这里注意下,在初始化声明数据库连接的时候已经定义了全局变量,后面的函数体内不能再次使用声明+赋值的形式进行赋值操作.
//db, err = sql.Open("mysql", dsn) //声明数据库类型,并使用预先定义完成的参数进连接 关键问题,如果编译执行的时候出现panic的话很有可能是这里使用了:=进行赋值操作.