首先下载github上的mysql驱动 https://github.com/go-sql-driver/mysql,放入GO_PATH环境变量下
导入包_“mysql”
import (
"database/sql"
"fmt"
_ "mysql" //一定要导入包,但不使用?
"os"
)
解释一下导入包名前面的"_"作用:
import 下划线(如:import _ github/demo)的作用:当导入一个包时,该包下的文件里所有init()函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来,仅仅是是希望它执行init()函数而已。这个时候就可以使用 import _ 引用该包。
上面的mysql驱动中引入的就是mysql包中各个init()方法,你无法通过包名来调用包中的其他函数。导入时,驱动的初始化函数会调用sql.Register将自己注册在database/sql包的全局变量sql.drivers中,以便以后通过sql.Open访问。
var (
Db *sql.DB
err error
)
func init() {
Db, err = sql.Open("mysql", "root:123456@tcp(localhost:3306)/test")
if err != nil {
fmt.Println("Open mysql error:", err)
os.Exit(-1)
}
sql.Open()函数的参数列表:数据库类型(mysql),数据库url(用户名:密码@tcp(url)/数据库名)
先定义结构体(最好)
type Sale struct {
Widget_id int
Qty int
Street string
City string
State string
Zip int
Sale_date string
}
然后使用占位符+预编译的方式进行插入数据
func (sale *Sale) AddSale() (err_ error) {
sql_str := "insert into sales(widget_id, qty, street, city, state, zip, sale_date) values(?, ?, ?, ?, ?, ?, ?)"
inStmt, err_ := Db.Prepare(sql_str) // 预编译
_, err_ = inStmt.Exec(sale.Widget_id, sale.Qty, sale.Street, sale.City, sale.State, sale.Zip, sale.Sale_date) // 执行预编译语句,传入参数
return err_
}
func main() {
sale := &Sale{Widget_id: 9, Qty: 80, Street: "Huanghe South Road", City: "Anyang Henan", State: "China", Zip: 455000, Sale_date: "2020-03-24"}
err_ := sale.AddSale()
if err_ != nil {
fmt.Println("sql execute err:", err_)
}
}
或者使用单元测试,新建xxx_test.go文件,写入以下内容
package main
import (
"testing"
)
func TestAddSale(t *testing.T) {
sale := &Sale{Widget_id: 2, Qty: 80, Street: "Huanghe South Road", City: "Anyang Henan", State: "China", Zip: 455000, Sale_date: "2022-02-13"}
sale.AddSale()
}
func (sale *Sale) GetRecordById() (ret *Sale, err_ error) {
sql_str := "select * from sales where widget_id = ?"
in_stmt, _ := Db.Prepare(sql_str)
row := in_stmt.QueryRow(sale.Widget_id)
if row == nil {
fmt.Println("No such record with id = ", sale.Widget_id)
return nil, errors.New("No such record with id = " + fmt.Sprintf("%d", sale.Widget_id))
}
ret = &Sale{}
err_ = row.Scan(&ret.Widget_id, &ret.Qty, &ret.Street, &ret.City, &ret.State, &ret.Zip, &ret.Sale_date)
return ret, err_
}
QueryRow()最多只接收一行查询结果,main函数中测试如下
func main() {
sale := &Sale{Widget_id: 9, Qty: 80, Street: "Huanghe South Road", City: "Anyang Henan", State: "China", Zip: 455000, Sale_date: "2020-03-24"}
ret, _ := sale.GetRecordById()
if ret != nil {
fmt.Println(*ret)
}
}
func (sale *Sale) GetAllRecord() (ret []*Sale, err_ error) {
sql_str := "select * from sales"
in_stmt, _ := Db.Prepare(sql_str)
rows, err_ := in_stmt.Query()
if err_ != nil {
fmt.Println("Error get all: ", err_)
return nil, err_
}
ret = make([]*Sale, 0)
for rows.Next() {
record := &Sale{}
err_ = rows.Scan(&record.Widget_id, &record.Qty, &record.Street, &record.City, &record.State, &record.Zip, &record.Sale_date)
if err_ != nil {
fmt.Println("Error get record: ", err_)
continue
}
ret = append(ret, record)
}
return ret, nil
}
Query()接收多行查询结果,main函数中测试如下
func main() {
sale := &Sale{}
ret2, _ := sale.GetAllRecord()
if ret2 != nil {
for _, record := range ret2 {
fmt.Println(*record)
}
}
}
//删除
func (this *Sale) DelRecordById() (err error) {
sql_str := "delete from sales where widget_id = ?"
in_stmt, _ := Db.Prepare(sql_str)
res, err := in_stmt.Exec(2)
if err != nil {
fmt.Println("Error del record :", err)
return errors.New("Error del record ")
}
n, err := res.RowsAffected()
if err != nil {
fmt.Println("Error del record :", err)
return errors.New("Error del record ")
}
fmt.Println("del success", n)
return nil
}
//更新
func (this *Sale) UpdateRecordById() (err error) {
sql_str := "update sales set qty = ? where widget_id = ?"
in_stmt, _ := Db.Prepare(sql_str)
res, err := in_stmt.Exec(this.Qty, this.Widget_id)
if err != nil {
return errors.New("update error")
}
n, _ := res.RowsAffected()
fmt.Println(n)
return nil
}
插入,删除,修改:Exec()
查询单个:QueryRow()
查询所有:Query()