1.下载并导入数据库驱动包

官方不提供实现,先下载第三方的实现,点击这里查看各种各样的实现版本。
这里选择了Go-MySQL-Driver这个实现。地址是:https://github.com/go-sql-driver/mysql/。

然后按照里面的说明下载驱动包:

$ go get github.com/go-sql-driver/mysql(个人感觉是让这个地址生效的语句)

最后导入包即可:

import "database/sql"
import _ "github.com/go-sql-driver/mysql" 

2.连接至数据库

db, err := sql.Open("mysql", "root:root@/uestcbook")

3.执行查询

(1)Exec

result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)","gopher",27,
)

(2)Query

rows, err := db.Query("SELECT name FROM users WHERE age = ?", age)
if err != nil {log.Fatal(err)
}
for rows.Next() {var name stringif err := rows.Scan(&name); err != nil {log.Fatal(err)}fmt.Printf("%s is %d\n", name, age)
}
if err := rows.Err(); err != nil {log.Fatal(err)
}

(3)QueryRow

var age int64
row := db.QueryRow("SELECT age FROM users WHERE name = ?", name)
err := row.Scan(&age)

(4)Prepared statements

age := 27
stmt, err := db.Prepare("SELECT name FROM users WHERE age = ?")
if err != nil {log.Fatal(err)
}
rows, err := stmt.Query(age)
// process rows

4. 事务

tx, err := db.Begin()
if err != nil {log.Fatal(err)
}

5. 各种方式效率分析

问题:db.exec和statement.exec和tx.exec的区别?

实例如下:

package mainimport ("strconv""database/sql"_ "github.com/go-sql-driver/mysql""fmt""time""log"
)var db = &sql.DB{}func init(){db,_ = sql.Open("mysql", "root:root@/book")
} func main() {insert()query()update()query()delete()
}func update(){//方式1 updatestart := time.Now()for i := 1001;i<=1100;i++{db.Exec("UPdate user set age=? where uid=? ",i,i)}end := time.Now()fmt.Println("方式1 update total time:",end.Sub(start).Seconds())//方式2 updatestart = time.Now()for i := 1101;i<=1200;i++{stm,_ := db.Prepare("UPdate user set age=? where uid=? ")stm.Exec(i,i)stm.Close()}end = time.Now()fmt.Println("方式2 update total time:",end.Sub(start).Seconds())//方式3 updatestart = time.Now()stm,_ := db.Prepare("UPdate user set age=? where uid=?")for i := 1201;i<=1300;i++{stm.Exec(i,i)}stm.Close()end = time.Now()fmt.Println("方式3 update total time:",end.Sub(start).Seconds())//方式4 updatestart = time.Now()tx,_ := db.Begin()for i := 1301;i<=1400;i++{tx.Exec("UPdate user set age=? where uid=?",i,i)}tx.Commit()end = time.Now()fmt.Println("方式4 update total time:",end.Sub(start).Seconds())//方式5 updatestart = time.Now()for i := 1401;i<=1500;i++{tx,_ := db.Begin()tx.Exec("UPdate user set age=? where uid=?",i,i)tx.Commit()}end = time.Now()fmt.Println("方式5 update total time:",end.Sub(start).Seconds())}func delete(){//方式1 deletestart := time.Now()for i := 1001;i<=1100;i++{db.Exec("DELETE FROM USER WHERE uid=?",i)}end := time.Now()fmt.Println("方式1 delete total time:",end.Sub(start).Seconds())//方式2 deletestart = time.Now()for i := 1101;i<=1200;i++{stm,_ := db.Prepare("DELETE FROM USER WHERE uid=?")stm.Exec(i)stm.Close()}end = time.Now()fmt.Println("方式2 delete total time:",end.Sub(start).Seconds())//方式3 deletestart = time.Now()stm,_ := db.Prepare("DELETE FROM USER WHERE uid=?")for i := 1201;i<=1300;i++{stm.Exec(i)}stm.Close()end = time.Now()fmt.Println("方式3 delete total time:",end.Sub(start).Seconds())//方式4 deletestart = time.Now()tx,_ := db.Begin()for i := 1301;i<=1400;i++{tx.Exec("DELETE FROM USER WHERE uid=?",i)}tx.Commit()end = time.Now()fmt.Println("方式4 delete total time:",end.Sub(start).Seconds())//方式5 deletestart = time.Now()for i := 1401;i<=1500;i++{tx,_ := db.Begin()tx.Exec("DELETE FROM USER WHERE uid=?",i)tx.Commit()}end = time.Now()fmt.Println("方式5 delete total time:",end.Sub(start).Seconds())}func query(){//方式1 querystart := time.Now()rows,_ := db.Query("SELECT uid,username FROM USER")defer rows.Close()for rows.Next(){var name stringvar id intif err := rows.Scan(&id,&name); err != nil {log.Fatal(err)}//fmt.Printf("name:%s ,id:is %d\n", name, id)
    }end := time.Now()fmt.Println("方式1 query total time:",end.Sub(start).Seconds())//方式2 querystart = time.Now()stm,_ := db.Prepare("SELECT uid,username FROM USER")defer stm.Close()rows,_ = stm.Query()defer rows.Close()for rows.Next(){var name stringvar id intif err := rows.Scan(&id,&name); err != nil {log.Fatal(err)}// fmt.Printf("name:%s ,id:is %d\n", name, id)
    }end = time.Now()fmt.Println("方式2 query total time:",end.Sub(start).Seconds())//方式3 querystart = time.Now()tx,_ := db.Begin()defer tx.Commit()rows,_ = tx.Query("SELECT uid,username FROM USER")defer rows.Close()for rows.Next(){var name stringvar id intif err := rows.Scan(&id,&name); err != nil {log.Fatal(err)}//fmt.Printf("name:%s ,id:is %d\n", name, id)
    }end = time.Now()fmt.Println("方式3 query total time:",end.Sub(start).Seconds())
}func insert() {//方式1 insert//strconv,int转string:strconv.Itoa(i)start := time.Now()for i := 1001;i<=1100;i++{//每次循环内部都会去连接池获取一个新的连接,效率低下db.Exec("INSERT INTO user(uid,username,age) values(?,?,?)",i,"user"+strconv.Itoa(i),i-1000)}end := time.Now()fmt.Println("方式1 insert total time:",end.Sub(start).Seconds())//方式2 insertstart = time.Now()for i := 1101;i<=1200;i++{//Prepare函数每次循环内部都会去连接池获取一个新的连接,效率低下stm,_ := db.Prepare("INSERT INTO user(uid,username,age) values(?,?,?)")stm.Exec(i,"user"+strconv.Itoa(i),i-1000)stm.Close()}end = time.Now()fmt.Println("方式2 insert total time:",end.Sub(start).Seconds())//方式3 insertstart = time.Now()stm,_ := db.Prepare("INSERT INTO user(uid,username,age) values(?,?,?)")for i := 1201;i<=1300;i++{//Exec内部并没有去获取连接,为什么效率还是低呢?stm.Exec(i,"user"+strconv.Itoa(i),i-1000)}stm.Close()end = time.Now()fmt.Println("方式3 insert total time:",end.Sub(start).Seconds())//方式4 insertstart = time.Now()//Begin函数内部会去获取连接tx,_ := db.Begin()for i := 1301;i<=1400;i++{//每次循环用的都是tx内部的连接,没有新建连接,效率高tx.Exec("INSERT INTO user(uid,username,age) values(?,?,?)",i,"user"+strconv.Itoa(i),i-1000)}//最后释放tx内部的连接
    tx.Commit()end = time.Now()fmt.Println("方式4 insert total time:",end.Sub(start).Seconds())//方式5 insertstart = time.Now()for i := 1401;i<=1500;i++{//Begin函数每次循环内部都会去连接池获取一个新的连接,效率低下tx,_ := db.Begin()tx.Exec("INSERT INTO user(uid,username,age) values(?,?,?)",i,"user"+strconv.Itoa(i),i-1000)//Commit执行后连接也释放了
        tx.Commit()}end = time.Now()fmt.Println("方式5 insert total time:",end.Sub(start).Seconds())
}

程序输出结果:

方式1 insert total time: 3.7952171
方式2 insert total time: 4.3162468
方式3 insert total time: 4.3392482
方式4 insert total time: 0.3970227
方式5 insert total time: 7.3894226
方式1 query total time: 0.0070004
方式2 query total time: 0.0100006
方式3 query total time: 0.0100006
方式1 update total time: 7.3394198
方式2 update total time: 7.8464488
方式3 update total time: 6.0053435
方式4 update total time: 0.6630379000000001
方式5 update total time: 4.5402597
方式1 query total time: 0.0070004
方式2 query total time: 0.0060004
方式3 query total time: 0.008000400000000001
方式1 delete total time: 3.8652211000000003
方式2 delete total time: 3.8582207
方式3 delete total time: 3.6972114
方式4 delete total time: 0.43202470000000004
方式5 delete total time: 3.7972172

6. 深入内部分析原因分析

(1)sql.Open("mysql", "username:pwd@/databasename")

功能:返回一个DB对象,DB对象对于多个goroutines并发使用是安全的,DB对象内部封装了连接池。

实现:open函数并没有创建连接,它只是验证参数是否合法。然后开启一个单独goroutines去监听是否需要建立新的连接,当有请求建立新连接时就创建新连接。

注意:open函数应该被调用一次,通常是没必要close的。

(2)DB.Exec()

功能:执行不返回行(row)的查询,比如INSERT,UPDATE,DELETE

实现:DB交给内部的exec方法负责查询。exec会首先调用DB内部的conn方法从连接池里面获得一个连接。然后检查内部的driver.Conn实现了Execer接口没有,如果实现了该接口,会调用Execer接口的Exec方法执行查询;否则调用Conn接口的Prepare方法负责查询。

(3)DB.Query()

功能:用于检索(retrieval),比如SELECT

实现:DB交给内部的query方法负责查询。query首先调用DB内部的conn方法从连接池里面获得一个连接,然后调用内部的queryConn方法负责查询。

(4)DB.QueryRow()

功能:用于返回单行的查询

实现:转交给DB.Query()查询

(5)db.Prepare()

功能:返回一个Stmt。Stmt对象可以执行Exec,Query,QueryRow等操作。

实现:DB交给内部的prepare方法负责查询。prepare首先调用DB内部的conn方法从连接池里面获得一个连接,然后调用driverConn的prepareLocked方法负责查询。

Stmt相关方法:

st.Exec()

st.Query()

st.QueryRow()

st.Close()

(6)db.Begin()

功能:开启事务,返回Tx对象。调用该方法后,这个TX就和指定的连接绑定在一起了。一旦事务提交或者回滚,该事务绑定的连接就还给DB的连接池。

实现:DB交给内部的begin方法负责处理。begin首先调用DB内部的conn方法从连接池里面获得一个连接,然后调用Conn接口的Begin方法获得一个TX。

TX相关方法:

//内部执行流程和上面那些差不多,只是没有先去获取连接的一步,因为这些操作是和TX关联的,Tx建立的时候就和一个连接绑定了,所以这些操作内部共用一个TX内部的连接。

tx.Exec()

tx.Query()

tx.QueryRow()

tx.Prepare()

tx.Commit()

tx.Rollback()

tx.Stmt()//用于将一个已存在的statement和tx绑定在一起。一个statement可以不和tx关联,比如db.Prepare()返回的statement就没有和TX关联。

例子:

  updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?")...tx, err := db.Begin()...res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203)

(7)源码中Stmt的定义

// Stmt is a prepared statement. Stmt is safe for concurrent use by multiple goroutines.

type Stmt struct {// Immutable:
db        *DB    // where we came from
query     string // that created the Stmt
stickyErr error  // if non-nil, this error is returned for all operations
closemu sync.RWMutex // held exclusively during close, for read otherwise.// If in a transaction, else both nil:
tx   *Txtxsi *driverStmtmu     sync.Mutex // protects the rest of the fields
closed bool// css is a list of underlying driver statement interfaces// that are valid on particular connections.  This is only// used if tx == nil and one is found that has idle// connections.  If tx != nil, txsi is always used.
css []connStmt}

(7)几个主要struct的内部主要的数据结构

参考资料

https://github.com/golang/go/wiki/SQLInterface

https://github.com/go-sql-driver/mysql/

http://golang.org/pkg/database/sql/

来源:https://www.cnblogs.com/tsiangleo/p/4483657.html

golang学习之旅:使用go语言操作mysql数据库(自己测试了)相关推荐

  1. go语言mysql操作_使用Go语言操作MySQL数据库的思路与步骤

    最近在做注册登录服务时,学习用Go语言操作MySQL数据库实现用户数据的增删改查,现将个人学习心得总结如下,另外附有代码仓库地址,欢迎各位有兴趣的fork. 软件环境:Goland.Navicat f ...

  2. c语言连接数据库例子,c语言操作mysql数据库小例子_互帮互助(C language MySQL database operation example _ mutual help).doc...

    这是精心收集的精品经典资料,值得下载保存阅读! c语言操作mysql数据库小例子_互帮互助(C language MySQL database operation example _ mutual h ...

  3. 用C语言操作MySQL数据库-通用版

    用C语言操作MySQL数据库 先看结构体: 以下代码块是用来连接数据库的通讯过程,要连接MYSQL,必须建立MYSQL实例,通过mysql_init初始化方能开始进行连接. typedef struc ...

  4. C语言mysql_ping实例代码_c语言操作mysql数据库(示例代码)

    c语言操作Mysql数据库,主要就是为了实现对数据库的增.删.改.查等操作,操作之前,得先连接数据库啊,而连接数据库主要有两种方法.一.使用mysql本身提供的API,在mysql的安装目录中可可以看 ...

  5. mysql基本命令大全_Django 学习笔记之 如何设置和操作 mysql 数据库

    我们之前学习了 在 django项目如何设置和操作sqlite 数据库. 在这一节中,我们会借由旧有思路来设置和操作 mysql 数据库.同时,我们会学习基本的mysql的SQL 命令,方便我们进行 ...

  6. c web mysql数据库_C语言操作MySQL数据库

    原作者博客http://www.cnblogs.com/nliao/archive/2010/09/09/1822660.html 先看结构体 ---------------------------- ...

  7. c语言将数据写入mysql中_用C语言操作MySQL数据库

    先看结构体 ---------------------------------------------- 以下代码块是用来连接数据库的通讯过程,要连接MYSQL,必须建立MYSQL实例,通过mysql ...

  8. linux mysql c语言编程,在Linux下通过C语言操作MySQL数据库

    2010年1月27日 晚 22:10 作者:longyun(http://www.linuxdiyf.com/mailto:mtd527@gmail.com) 续:小弟最近想学习数据库,并想开发一个简 ...

  9. c 对一个mysql数据库进行操作_用C语言操作MySQL数据库

    函数 描述 mysql_affected_rows() 返回上次UPDATE.DELETE或INSERT查询更改/删除/插入的行数. mysql_autocommit() 切换autocommit模式 ...

最新文章

  1. 企业网络推广中用户行为到底能为企业网络推广带来多少影响?
  2. namecheap教程
  3. id选择器、标签选择器、类选择器、交集选择器、并集选择器
  4. Ubuntu: 创建PlayOnLinux快捷键 Create PlayOnLinux Application Desktop
  5. 爬取http://ycb-benchmarks.s3-website-us-east-1.amazonaws.com/的链接并下载文件
  6. 百度地图api中文乱码
  7. Python 调用IDM下载器
  8. PHP实现免费代理池
  9. 新浪微博客户端开发之发布微博
  10. Godot检查器增强插件
  11. 基于matlab的2psk功率,基于matlab的相移键控系统仿真.doc
  12. 群晖NAS误删30T数据成功恢复全过程
  13. hadoop-common2.7源码分析之ProtobufRpcEngine(RPC实现)
  14. Hive入门教程<2> | hive在centos7下的安装部署
  15. Web Components 学习笔记一: Web Components是什么?解决了什么问题?
  16. python + selenium +pyquery 爬虫 爬取 1688详情图片 阿里巴巴详情图片 与标题 下载图片并进行压缩
  17. 关于华为认证hcip有哪些问题?
  18. php简转繁体,使用PHP实现繁体与简体互转
  19. 博弈论——1218:取石子游戏
  20. 树莓派蓝屏_实战树莓派安装Windows XP

热门文章

  1. sublime67linter-php,Sublime Text 3 搭建 React.js 开发环境
  2. R语言——导入Excel表格数据方法
  3. 05_ClickHouse、MergeTree系列引擎概述与存储结构、建表模板、建表语句、MergeTree设置、建表示例、数据存储、数据片段(data part)
  4. Python多继承mro示例
  5. nc65语义模型设计_文本匹配方法系列––多维度语义交互匹配模型
  6. python把数据写入excel_Python向excel中写入数据的方法
  7. 如何查询oracle死锁,Oracle死锁查看和解决办法汇总
  8. gba徽章机器人_徽章战士GBA攻略
  9. OpenCV—中值滤波
  10. OpenCV—基本数据结构与示例