package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
)
func main() {
// 连接数据库
db, err := sql.Open("mysql", "root:1234567@tcp(127.0.0.1:3306)/test")
if err != nil {
log.Fatal(err)
}
// 确认地址是否有效
err = db.Ping()
if err != nil {
fmt.Println("dberr=", err)
}
// var (
// id int
// name string
// )
// 将查询发送到数据库。像往常一样,我们检查错误
// 其次,只要有一个开放的结果集(由行表示),
// 底层连接就会繁忙,不能用于任何其他查询。
// 这意味着它在连接池中不可用。如果您使用row .
// next()迭代所有的行,最终您将读取最后一行,
// 而row . next()将遇到一个内部的EOF错误并调用
// rows.Close()给你。但是,如果出于某种原因,
// 您退出该循环(早期返回),那么行不会被关闭,
// 连接仍然是打开的。(如果行,则自动关闭。但是,
// 下一个()返回false是因为错误。这是一种很容易耗尽
// 资源的方法。
// stmt, err := db.Prepare("select id,name from store where id =?", 1).Scan(&name)
// 单列查询
stmt, err := db.Prepare("select name from store where id =?")
if err != nil {
log.Fatal(err)
}
//推迟 close 很重要 始终保证推出 调用Close 就算在代码最后
// 如果以及关闭也可多次调用
// 注意: 首先检查错误,并且只有在没有错误的情况下才调用Close()
defer stmt.Close()
// 准备、执行语句 并关闭准备好的语句。这是到数据库的三次往返
// rows, err := stmt.Query(3)
var names string
// 单列查询
err = stmt.QueryRow(3).Scan(&names)
// if err != nil {
// log.Fatal(err)
// }
fmt.Println(names)
// defer rows.Close()
//遍历执行 查询出来的数据
// for rows.Next() {
//我们使用row . scan()将每行中的列读入变量。
// 当您遍历行并将它们扫描到目标变量时,
// Go在后台执行数据类型转换。它基于目标变量的类型。
// 意识到这一点可以清理代码并避免重复工作。
// err := rows.Scan(&id, &name)
// 抱着在循环的末尾检查错误,如果在循环期间有错误,
// 需要知道他,不要仅仅假设循环迭代完成后在处理错误
// if err != nil {
// log.Fatal(err)
// }
// log.Println(id, name)
// }
//在遍历行之后,我们检查错误
// err = rows.Err()
if err != nil {
log.Fatal(err)
}
defer db.Close()
}