初始化创建数据库连接

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的话很有可能是这里使用了:=进行赋值操作.