golang怎么连接mysql数据库

golang操作mysql安装go get "
github.com/go-sql-driver/mysql"

go get "
github.com/jmoiron/sqlx"
连接数据库var Db *sqlx.DB
db, err := sqlx.Open("
mysql"
,"
username:password@tcp(ip:port)/database?charset=utf8"
)
Db = db

连接2

package main
import (
"
database/sql"

"
fmt"

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

)
var db *sql.DB //全局对象db

func initDB() (err error) {
db, err = sql.Open("
mysql"
,"
root:admin123@tcp(127.0.0.1:3306)/dududu?charset=utf8"
)
if err!=nil{
return err
}
err = db.Ping() //校验数据库连接
if err!=nil{
return err
}
return nil
}

type beautiful struct {
spu_id string
title string
price string
}

func queryRowDemo() {
sqlStr :="
select spu_id,title,price from dududu_shops where id = ?"

var u beautiful
err:=db.QueryRow(sqlStr,101).Scan(&
amp;
u.spu_id,&
amp;
u.title,&
amp;
u.price)
if err!=nil{
fmt.Println("
2"
,err)
}
fmt.Println(u)
}


func main() {
err:=initDB()
if err!=nil{
fmt.Println("
1"
,err)
return
}
queryRowDemo()
} 处理类型(Handle Types)

sqlx设计和database/sql使用方法是一样的。包含有4中主要的handle types:

  • sqlx.DB - 和sql.DB相似,表示数据库。

  • Golang如何连接MySQL数据库

    sqlx.Tx - 和sql.Tx相似,表示事物。

  • sqlx.Stmt - 和sql.Stmt相似,表示prepared statement。

  • sqlx.NamedStmt - 表示prepared statement(支持named parameters)

所有的handler types都提供了对database/sql的兼容,意味着当你调用sqlx.DB.Query时,可以直接替换为sql.DB.Query.这就使得sqlx可以很容易的加入到已有的数据库项目中。

此外,sqlx还有两个cursor类型:

  • sqlx.Rows - 和sql.Rows类似,Queryx返回。

  • sqlx.Row - 和sql.Row类似,QueryRowx返回。

相比database/sql方法还多了新语法,也就是实现将获取的数据直接转换结构体实现。

  • Get(dest interface{}, &
    hellip;
    ) error

  • Select(dest interface{}, &
    hellip;
    ) error

建表

以下所有示例均已以下表结构作为操作基础。

CREATE TABLE `userinfo` (
`uid` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) DEFAULT NULL,
`password` VARCHAR(32) DEFAULT NULL,
`department` VARCHAR(64) DEFAULT NULL,
`email` varchar(64) DEFAULT NULL,
PRIMARY KEY (`uid`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 Exec使用

Exec和MustExec会从连接池中取出一个连接,然后执行相应的查询操作。对于不支持ad-hoc query execution的驱动,在操作执行的背后会创建一个prepared statement。在结果返回前这个connection会返回到连接池中。

需要注意的是不同的数据库类型使用的占位符不同,mysql采用?作为占位符号。

  • MySQL 使用?

  • PostgreSQL 使用1,1,2等等

  • SQLite 使用?或$1

  • Oracle 使用:name

Exec增删该示例

查询语法使用Query后续会提到

package main

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

"
github.com/jmoiron/sqlx"

"
fmt"

)

var Db *sqlx.DB

func init() {
db, err := sqlx.Open("
mysql"
, "
stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8"
)
if err != nil {
fmt.Println("
open mysql failed,"
, err)
return
}
Db = db
}

func main() {
result, err := Db.Exec("
INSERT INTO userinfo (username, password, department,email) VALUES (?, ?, ?,?)"
,"
wd"
,"
123"
,"
it"
,"
wd@163.com"
)
if err != nil{
fmt.Println("
insert failed,error: "
, err)
return
}
id,_ := result.LastInsertId()
fmt.Println("
insert id is :"
,id)
_, err1 := Db.Exec("
update userinfo set username = ? where uid = ?"
,"
jack"
,1)
if err1 != nil{
fmt.Println("
update failed error:"
,err1)
} else {
fmt.Println("
update success!"
)
}
_, err2 := Db.Exec("
delete from userinfo where uid = ? "
, 1)
if err2 != nil{
fmt.Println("
delete error:"
,err2)
}else{
fmt.Println("
delete success"
)
}

}
//insert id is : 1
//update success!
//delete success sql预声明(Prepared Statements)

对于大部分的数据库来说,当一个query执行的时候,在sql语句数据库内部声明已经声明过了,其声明是在数据库中,我们可以提前进行声明,以便在其他地方重用。

stmt, err := db.Prepare(`SELECT * FROM place WHERE telcode=?`)
row = stmt.QueryRow(65)

tx, err := db.Begin()
txStmt, err := tx.Prepare(`SELECT * FROM place WHERE telcode=?`)
row = txStmt.QueryRow(852)

当然sqlx还提供了Preparex()进行扩展,可直接用于结构体转换

stmt, err := db.Preparex(`SELECT * FROM place WHERE telcode=?`)
var p Place
err = stmt.Get(&
amp;
p, 852) Query

row结果通过使用database/sql中的Rows来获取。Query返回一个sql.Rows对象和一个error对象。

在使用的时候应该吧Rows当成一个游标而不是一系列的结果。尽管数据库驱动缓存的方法不一样,通过Next()迭代每次获取一列结果,对于查询结果非常巨大的情况下,可以有效的限制内存的使用,Scan()利用reflect把sql每一列结果映射到go语言的数据类型如string,[]byte等。如果你没有遍历完全部的rows结果,一定要记得在把connection返回到连接池之前调用rows.Close()。

Query返回的error有可能是在server准备查询的时候发生的,也有可能是在执行查询语句的时候发生的。举个例子,即使在数据库尝试10次发现或创建一个可用的连接时,也有可能从连接池中获取到一个糟糕的连接。通常,错误主要源于SQL语句的错误、类似匹配的错误和域名或表名的错误。

在大多数情况下,无论驱动如何使用缓存,Rows.Scan()都会将从驱动获取的数据复制一份。特殊类型sql.RawBytes可以用来从驱动返回的数据总获取一个zero-copy的slice byte。在下一次调用 Next 时,该值将失效,因为它所指向的内存已被驱动程序重写为其他数据。

Query使用的connection在所有的rows通过Next()遍历完后或者调用rows.Close()后释放。

示例:

package main

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

"
github.com/jmoiron/sqlx"

"
fmt"

)

var Db *sqlx.DB

func init() {
db, err := sqlx.Open("
mysql"
, "
stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8"
)
if err != nil {
fmt.Println("
open mysql failed,"
, err)
return
}
Db = db
}

func main() {
rows, err := Db.Query("
SELECT username,password,email FROM userinfo"
)
if err != nil{
fmt.Println("
query failed,error: "
, err)
return
}
for rows.Next() { //循环结果
var username,password,email string
err = rows.Scan(&
amp;
username, &
amp;
password, &
amp;
email)
println(username,password,email)
}

}
//wd 123 wd@163.com
//jack 1222 jack@165.com Queryx

Queryx和Query行为很相似,不过返回一个sqlx.Rows对象,支持扩展的scan行为,同时可将对数据进行结构体转换。

示例:

package main

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

"
github.com/jmoiron/sqlx"

"
fmt"

)

var Db *sqlx.DB

type stu struct {
Username string `db:"
username"
`
Password string `db:"
password"
`
Department string `db:"
department"
`
Email string `db:"
email"
`
}

func init() {
db, err := sqlx.Open("
mysql"
, "
stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8"
)
if err != nil {
fmt.Println("
open mysql failed,"
, err)
return
}
Db = db
}

func main() {
rows, err := Db.Queryx("
SELECT username,password,email FROM userinfo"
)
if err != nil{
fmt.Println("
Qeryx failed,error: "
, err)
return
}
for rows.Next() { //循环结果
var stu1 stu
err = rows.StructScan(&
amp;
stu1)// 转换为结构体
fmt.Println("
stuct data:"
,stu1.Username,stu1.Password)
}
}
//stuct data: wd 123
//stuct data: jack 1222 QueryRow和QueryRowx

QueryRow和QueryRowx都是从数据库中获取一条数据,但是QueryRowx提供scan扩展,可直接将结果转换为结构体。

package main

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

"
github.com/jmoiron/sqlx"

"
fmt"

)

var Db *sqlx.DB

type stu struct {
Username string `db:"
username"
`
Password string `db:"
password"
`
Department string `db:"
department"
`
Email string `db:"
email"
`
}

func init() {
db, err := sqlx.Open("
mysql"
, "
stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8"
)
if err != nil {
fmt.Println("
open mysql failed,"
, err)
return
}
Db = db
}

func main() {
row := Db.QueryRow("
SELECT username,password,email FROM userinfo where uid = ?"
,1) // QueryRow返回错误,错误通过Scan返回
var username,password,email string
err :=row.Scan(&
amp;
username,&
amp;
password,&
amp;
email)
if err != nil{
fmt.Println(err)
}
fmt.Printf("
this is QueryRow res:[%s:%s:%s]\n"
,username,password,email)
var s stu
err1 := Db.QueryRowx("
SELECT username,password,email FROM userinfo where uid = ?"
,2).StructScan(&
amp;
s)
if err1 != nil{
fmt.Println("
QueryRowx error :"
,err1)
}else {
fmt.Printf("
this is QueryRowx res:%v"
,s)
}
}
//this is QueryRow res:[wd:123:wd@163.com]
//this is QueryRowx res:{jack 1222 jack@165.com} Get 和Select(非常常用)

Get和Select是一个非常省时的扩展,可直接将结果赋值给结构体,其内部封装了StructScan进行转化。使用Get方法来获取单个结果后再使用Scan方法,使用Select方法则可获取结果切片。

示例:

package main

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

"
github.com/jmoiron/sqlx"

"
fmt"

)

var Db *sqlx.DB

type stu struct {
Username string `db:"
username"
`
Password string `db:"
password"
`
Department string `db:"
department"
`
Email string `db:"
email"
`
}

func init() {
db, err := sqlx.Open("
mysql"
, "
stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8"
)
if err != nil {
fmt.Println("
open mysql failed,"
, err)
return
}
Db = db
}

func main() {
var stus []stu
err := Db.Select(&
amp;
stus,"
SELECT username,password,email FROM userinfo"
)
if err != nil{
fmt.Println("
Select error"
,err)
}
fmt.Printf("
this is Select res:%v\n"
,stus)
var s stu
err1 := Db.Get(&
amp;
s,"
SELECT username,password,email FROM userinfo where uid = ?"
,2)
if err1 != nil{
fmt.Println("
GET error :"
,err1)
}else {
fmt.Printf("
this is GET res:%v"
,s)
}
}
//this is Select res:[{wd 123 wd@163.com} {jack 1222 jack@165.com}]
//this is GET res:{jack 1222 jack@165.com} 事务(Transactions)

事务操作是通过三个方法实现:

Begin():开启事务

Commit():提交事务(执行sql)

Rollback():回滚

使用流程:

tx, err := db.Begin()
err = tx.Exec(...)
err = tx.Commit()

//或者使用sqlx扩展的事务
tx := db.MustBegin()
tx.MustExec(...)
err = tx.Commit()

为了维持一个持续的连接状态,Tx对象必须绑定和控制单个连接。在整个生命周期期间,一个Tx将保持连接,直到调用commit或Rollback()方法将其释放。必须非常谨慎地调用这些函数,否则连接将一直被占用,直到被垃圾回收。

使用示例:

package main

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

"
github.com/jmoiron/sqlx"

"
fmt"

)

var Db *sqlx.DB

func init() {
db, err := sqlx.Open("
mysql"
, "
stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8"
)
if err != nil {
fmt.Println("
open mysql failed,"
, err)
return
}
Db = db
}

func main() {
tx, err := Db.Beginx()
_, err = tx.Exec("
insert into userinfo(username,password) values(?,?)"
, "
Rose"
,"
2223"
)
if err != nil {
tx.Rollback()
}
_, err = tx.Exec("
insert into userinfo(username,password) values(?,?)"
, "
Mick"
,222)
if err != nil {
fmt.Println("
exec sql error:"
,err)
tx.Rollback()
}
err = tx.Commit()
if err != nil {
fmt.Println("
commit error"
)
}

} 连接池设置

当连接池中没有可用空闲连接时,连接池会自动创建连接,并且其增长是无限制的。最大连接数可以通过调用DB.SetMaxOpenConns来设置。未使用的连接标记为空闲,如果不需要则关闭。为了减少连接的开启和关闭次数,可以利用DB.SetMaxIdleConns方法来设定最大的空闲连接数。

注意:该设置方法golang版本至少为1.2

  • DB.SetMaxIdleConns(n int) 设置最大空闲连接数

  • DB.SetMaxOpenConns(n int) 设置最大打开的连接数

  • DB.SetConnMaxIdleTime(time.Second*10) 间隔时间

示例:

package main

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

"
github.com/jmoiron/sqlx"

"
fmt"

)

var Db *sqlx.DB

func init() {
db, err := sqlx.Open("
mysql"
, "
stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8"
)
if err != nil {
fmt.Println("
open mysql failed,"
, err)
return
}
Db = db
Db.SetMaxOpenConns(30)
Db.SetMaxIdleConns(15)

} 案例使用var Db *sqlx.DB
db, err := sqlx.Open("
mysql"
,"
root:admin123@tcp(127.0.0.1:3306)/dududu?charset=utf8"
)
Db = db

rows, err := Db.Query("
SELECT spu_id,title,price FROM dududu_shops"
)

if err != nil{
fmt.Println("
query failed,error: "
, err)
return
}
for rows.Next() { //循环结果
var spu_id,title,price string
err = rows.Scan(&
amp;
spu_id, &
amp;
title, &
amp;
price)
println(spu_id,title,price)
}

Golang已经成为一个流行的编程语言,全面支持开发不同类型的应用程序。可以构建各种强大和可靠的工具和系统,为企业和开发人员提供更好的体验。MySQL的支持也是golang表现的一大亮点。这篇文章将向您展示如何使用golang连接MySQL数据库和执行基本的CRUD操作。
1. 环境设置和配置MySQL数据库
在开始编写golang程序之前,我们首先需要安装一个MySQL服务器。对于Windows用户,建议使用XAMPP或WAMP服务。对于Linux用户,可以在终端中使用apt-get等命令安装MySQL。同时,我们需要使用MySQL的驱动程序。为此,在终端中使用以下命令安装它:
```
go get -u github.com/go-sql-driver/mysql
```
2. 建立MySQL数据库连接
我们已经准备好MySQL服务和驱动程序,下一步是建立连接。为此,我们需要使用以下代码:
```go
import (
\"database/sql\"
_ \"github.com/go-sql-driver/mysql\"
)
func main() {
// 连接数据库
db, err := sql.Open(\"mysql\", \"username:password@tcp(host:port)/dbname?charset=utf8\")

if err != nil {
panic(err.Error())
}

// 确保连接关闭
defer db.Close()
}
```
重要的是要记住,在连接MySQL数据库时确保正确的用户名,密码,主机端口和数据库名称。调用‘sql.Open’函数返回一个实例,它充当MySQL数据库的代表。
3. 执行MySQL CRUD操作
MySQL支持四种类型的基本操作:创建,读取,更新和删除。下面描述了如何在Golang中执行这些操作:
3.1 创建操作
通过执行SQL语句可以轻松创建操作。为了在golang程序中执行SQL语句,我们需要使用以下代码:
```go
func Create(row Row) (int64, error) {
\tsql := \"INSERT INTO users(name, age, email) VALUES(?, ?, ?)\"
\treturn db.Exec(sql, row.Name, row.Age, row.Email)
}
```
该代码将参数插入到SQL查询中然后执行。结果返回新插入记录的ID号。
3.2 读取操作
类查询操作可以使用SQL查询语句描述。SQLite需要在Go中实现该功能。使用以下代码:
```go
func Read(id int64) (Row, error) {
\tvar row Row
\terr := db.QueryRow(\"SELECT id, name, age, email FROM users WHERE id=?\", id).Scan(&row.ID, &row.Name, &row.Age, &row.Email)
\treturn row, err
}
```
3.3 更新操作
执行操作可以使用SQL更新查询语句轻松描述。使用以下代码:
```go
func Update(row Row) error {
\tsql := \"UPDATE users SET name=?, age=?, email=? WHERE id=?\"
\t_, err := db.Exec(sql, row.Name, row.Age, row.Email, row.ID)
\treturn err
}
```
3.4 删除操作
删除操作可以使用SQL删除操作轻松描述。使用以下代码:
```go
func Delete(id int64) error {
\tsql := \"DELETE FROM users WHERE id=?\"
\t_, err := db.Exec(sql, id)
\treturn err
}
```
结论
如你所见,golang可以很容易地连接到MySQL数据库。我们已经学习了如何配置和准备MySQL数据库,建立MySQL数据库连接,以及执行基本的CRUD操作。使用这些技术,您可以轻松地将Golang的功能连接到MySQL数据库,并更好地支持您的应用程序。