go-sql-driver/mysql基本使用 | 青训营笔记

707 阅读2分钟

这是我参加第五届青训营伴学笔记创作活动的第二天.

go-mysql-driver是什么?

一个针对go的database/sql包的mysql驱动.

有什么特点?

  • 速度快并且轻量.
  • 基于原生go实现,没有使用c-bindings.
  • 能够基于多种协议建立连接(TCP/IPV4, TCP/IPV6等).
  • 支持占位符.
  • 支持自动连接池.
  • ...

如何使用它?(基本使用)

  1. 首先安装go-sql-driver/mysql驱动
$ go get -u github.com/go-sql-driver/mysql
  1. 以副作用形式加载mysql驱动包就可以开始使用了.
  2. 编写相关代码

import (
	"database/sql"
	"time"

	_ "github.com/go-sql-driver/mysql"
)


func main(){
    db,err :=sql.Open("mysql","用户名:密码@/数据库名称?一些你想加的参数")
    defer db.Close()

    err = db.Ping()
    if err != nil {
            // do something here
    }
}

需要注意的是,sql.Open仅仅建立了与数据库通信的抽象,同时他不会检查输入的参数是否正确,真正的连接会延迟到程序第一次执行命令(增删改查等)才会建立.

所以mysql包贴心地提供了Ping函数,来检查能正确连接数据库,

从数据库中获取数据

  1. 使用db.Query语句
var (
	id int
	name string
)
rows, err := db.Query("select id, name from users where id = ?", 1)
if err != nil {
	log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
	err := rows.Scan(&id, &name)
	if err != nil {
		log.Fatal(err)
	}
	log.Println(id, name)
}
err = rows.Err()
if err != nil {
	log.Fatal(err)
}

直接使用db.Query进行查询的话可能会存在安全问题,比如看以下代码:

...
rows, err := db.Query("select id, name from users where id = ?", "1 or 1=1")
if err != nil {
	log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
	err := rows.Scan(&id, &name)
	if err != nil {
		log.Fatal(err)
	}
	log.Println(id, name)
}
...

这么做的话直接寄了.

go-sql-driver/mysql贴心地提供了prepared statements哈哈哈.


stmt, err := db.Prepare("select id, name from users where id = ?")
if err != nil {
	log.Fatal(err)
}
defer stmt.Close()
rows, err := stmt.Query(1)
if err != nil {
	log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
	// ...
}
if err = rows.Err(); err != nil {
	log.Fatal(err)
}

跟java的mybatis类似(至于为什么不举其他例子,因为我只知道个mybatis有..),通过预编译手段以及使用?占位符能有效防止sql注入.

stmt, err := db.Prepare("select id, name from users where id = ?")
if err != nil {
	log.Fatal(err)
}
defer stmt.Close()
rows, err := stmt.Query(1)
if err != nil {
	log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
	// ...
}
if err = rows.Err(); err != nil {
	log.Fatal(err)
}

修改数据集最好使用db.Exec进行修改,千万别用db.Query执行修改.因为Query函数要求返回结果集,

这个结果集对应的sql连接在使用结果后需要关闭,如果用Query执行修改语句会导致该连接一直无法得到关闭.

至于事务这种高级特性以及相关用法还是等你自己进行探索吧.

go-sql-driver/mysql仓库

go-sql-driver/mysql例子

go-sql-driver/mysql官方文档(基础)