Go Web --- 使用MySQL

简略介绍

  在Go语言中,如果要连接并操作数据库,那么就要自己安装对应的数据库驱动,每一种数据库的驱动都不同,但是Go语言提供了一套抽象层接口来调用底层的驱动,类似于PHP语言中PDO。

  

安装mysql驱动

  使用go语言的go get命令即可,  

go get github.com/go-sql-driver/mysql

  可能你在运行这条命令的时候出现这种情况:

warning: GOPATH set to GOROOT (/usr/local/go) has no effect

  这个时候,你可以查看一下你的PATH环境变量和GOROOT环境变量。看是不是你的GOROOT也在PATH里面。

  首先,如果你的go安装目录是在/usr/local目录下,那么你就可以不要设置GOROOT环境变量,只有当你的安装目录不是/usr/local目录下的时候,才指定GOROOT环境变量,

  我的go安装路径是/usr/local/go目录,所以我的PATH变量值为/usr/local/go/bin。

  各种包,包括这里的mysql驱动,都默认安装在$HOME/go/src/github.com目录下的。

 

设置连接数据库的参数

  func Open(driverName, dataSourceName string) (*DB, error)

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"  //_表示只使用init方法
)

func main() {
	//func Open(driverName, dataSourceName string) (*DB, error)
	_, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")
	if err != nil {
		panic(err)
	} else {
		fmt.Println("数据库连接成功")
	}
}

  注意,这个代码上面的标题并不是“连接数据库”,而是设置“连接数据库的参数”,因为:

  这里有一个坑:上面这段代码,无论你的用户名,还是密码,甚至是ip和端口都错了,那么他也会输出“数据库连接成功”

  Go Web编程(Go web Programming)中这样说的:

  Open函数在执行的时候并不会真正的与数据库进行连接,他甚至不会检查用户给定的参数;Open函数的真正作用是设置好连接数据库所需的各个结构,并以惰性的方式,等到真正需要时才建立相应的数据库连接。

  怎么样才知道你的数据库参数是否正确呢?执行一条SQL语句就行了。

 

执行SQL语句的两个方法

  func (s *Stmt) Query(args ...interface{}) (*Rows, error) 

  用来执行select这种有结果集的SQL查询操作

 

  func (s *Stmt) Exec(args ...interface{}) (Result, error)

  用来执行update、insert、delete这几种数据库操作命令

 

测试使用的数据表(shop)

mysql> desc fruit;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| name  | char(30) | NO   |     | NULL    |                |
| price | int(11)  | NO   |     | 99      |                |
+-------+----------+------+-----+---------+----------------+

  

使用Query方法进行select操作,返回结果集

//func Open(driverName, dataSourceName string) (*DB, error)
db, _ := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")

//关闭数据库连接
//func (db *DB) Close() error
defer db.Close()

//func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
rows, _ := db.Query("select * from fruit")

//获取结果集中的字段名
//func (rs *Rows) Columns() ([]string, error)
fields, _ := rows.Columns()
fmt.Println(fields) //[id name age gender]

//声明几个变量,用来保存从数据库中读出的每一行记录
var id int
var name string
var price int

//循环遍历结果集
//func (rs *Rows) Next() bool
for rows.Next() {
	//将结果集中的一行记录的值赋值给变量
	//func (rs *Rows) Scan(dest ...interface{}) error
	rows.Scan(&id, &name, &price)
	//注意:必须和结果集的字段数量相同,并且顺序、字段名必须对应,否则保存到变量中的数据会有问题
	fmt.Println(id, name, price)
	
}

//释放结果集,注意,结果集是在数据取完之后释放,不是取一条数据就释放一次
rows.Close()

  

 

使用QueryRow获取一条记录

  func (db *DB) QueryRow(query string, args ...interface{}) *Row

  QueryRow使用起来很方便:QueryRow("sql").Scan("field1","field2")    

 

 

使用Exec方法进行增删改

  insert

db, _ := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")
defer db.Close()

//func (db *DB) Exec(query string, args ...interface{}) (Result, error)
result, _ := db.Exec("insert into fruit (id,name,price) values (5,'pomelo',8)")

//func (dr driverResult) LastInsertId() (int64, error)
id, _ := result.LastInsertId()
fmt.Println(id) //5

//func (dr driverResult) RowsAffected() (int64, error)
num, _ := result.RowsAffected()
fmt.Println(num) //1

  

  update

db, _ := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")
defer db.Close()

result, _ := db.Exec("update fruit set price=20 where id > 3")

//func (dr driverResult) RowsAffected() (int64, error)
num, _ := result.RowsAffected()
fmt.Println(num) //2

  

  delete

db, _ := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")
defer db.Close()

result, _ := db.Exec("delete  from fruit")

//func (dr driverResult) RowsAffected() (int64, error)
num, _ := result.RowsAffected()
fmt.Println(num) // 5

  

 

  

预处理SQL

  使用预处理就是将SQL语句和参数分离,参数可以单独绑定值,这样一定程度上可以防止SQL注入。

  进行与处理之后,返回的Stmt对象,Stmt对象也有Exec和Query方法,并且这两个方法和DB.Exec、DB.Query、DB.QueryRow方法完全相同。

  预处理查

db, _ := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")

defer db.Close()

//func (db *DB) Prepare(query string) (*Stmt, error)
stmt, _ := db.Prepare("select * from fruit where id=? or name=?")

//如果预处理的SQL语句是查操作,那么就使用Query方法执行SQL命令,返回结果集
//func (s *Stmt) Query(args ...interface{}) (*Rows, error)
rows, _ := stmt.Query(3, "apple")
var id int
var name string
var price int
for rows.Next() {
	rows.Scan(&id, &name, &price)
	fmt.Println(id, name, price)
}

rows.Close()

  

  预处理增删改

db, _ := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")

defer db.Close()

stmt, _ := db.Prepare("update fruit set price=30 where id>?")
//func (s *Stmt) Exec(args ...interface{}) (Result, error)
result, _ := stmt.Exec(1)
fmt.Println(result.RowsAffected()) //4 <nil>

stmt, _ = db.Prepare("insert into fruit values (?,?,?)")
result, _ = stmt.Exec(6, "kaki", 20) // 6 <nil>
fmt.Println(result.LastInsertId())

stmt, _ = db.Prepare("delete from fruit where id > ?")
result, _ = stmt.Exec(3)
fmt.Println(result.RowsAffected()) //3 <nil>

 

posted @ 2018-06-13 00:26  寻觅beyond  阅读(1234)  评论(0)    收藏  举报
返回顶部