对于许多Web应用程序而言,数据库都是其核心所在,数据库几乎可以用来存储你想查询和修改的任何信息。
但是Go本身没有内置任何的驱动来操作数据库,但是 Go 内置 database/sql,里面定义了一些接口,用于可以根据接口开发相应数据库的驱动。比如:MySQL、PostgreSQL是不同的数据库,但是我们都可以使用 database/sql 进行操作。常见的数据库驱动如下:
Mysql: https://github.com/go-sql-driver/mysql
MyMysql: https://github.com/ziutek/mymysql
Postgres: https://github.com/lib/pq
Tidb: https://github.com/pingcap/tidb
SQLite: https://github.com/mattn/go-sqlite3
MsSql: https://github.com/denisenkom/go-mssqldb
Oracle: https://github.com/mattn/go-oci8
这里我们就使用PostgreSQL进行演示。
连接数据库
要想使用Go操作PostgreSQL,那么首先要和数据库之间建立连接,得到DB对象。
import (
"database/sql"
_ "github.com/lib/pq"
)
database/sql 是 Go 的标准库之一,它提供了一系列接口方法,用于访问关系数据库。它并不会提供数据库特有的方法,那些特有的方法会交给具体的数据库驱动去实现。
我们正在加载的驱动是匿名的,导入之后该驱动会自行初始化并注册到 Go 的 database/sql 上下文中,因此我们就可以 database/sql 包提供的方法去访问数据库了.
下面是建立连接,建立连接的话使用 sql.Open 函数:
func Open(driverName, dataSourceName string) (*DB, error) {
/*
driverName: 这个名字就是数据库驱动注册到 database/sql 时所使用的名字
如果是MySQL数据库的话, 那么就是"mysql"; 如果是PostgreSQL数据库的话, 那么就是"postgres";
dataSourceName: 数据库的连接信息, 这个连接包括了数据库的用户名、密码、数据库主机以及连接的数据库名等信息
用户名:密码@协议(地址:端口)/数据库?参数=参数值
db, err := sql.Open("postgres", "postgres:zgghyys123@tcp(localhost:5432)/postgres")
*/
}
代码演示一下:
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
func main() {
// 这里的open函数只是验证参数是否合法, 不会创建和数据库的连接; 得到的仅仅是一个sql.DB对象, 当进行数据库查询的时候才会建立网络连接
// sql.DB 表示操作数据库的抽象接口, 但不是所谓的数据库连接对象, 它只有在需要使用时才会创建连接
// 注意: dataSourceName结尾的 sslmode=disable, 如果没有的话会报错: pq: SSL is not enabled on the server
db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
if err != nil {
panic(err)
}
// 记得关闭连接, 这里使用defer, 由于该函数返回一个error, 所以我们放在匿名函数中
defer func() {_ = db.Close()}()
// 如果要立刻检测数据库源是否能连接到指定的数据库, 需要调用返回值的Ping方法
fmt.Println(db.Ping()) //
// 打印nil证明没有错误
}
现在来看看go是如何操作mysql的
- 安装驱动
go get github.com/go-sql-driver/mysql
- 导入需要的库
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
- 连接数据库
func main() {
//"用户名:密码@[连接方式](主机名:端口号)/数据库名"
db, _ := sql.Open("mysql", "root:123456@(localhost)/world") // 设置连接数据库的参数
defer db.Close() //关闭数据库
err := db.Ping() //连接数据库
if err != nil {
fmt.Println("数据库连接失败") //连接失败
return
} else {
fmt.Println("数据库连接成功") //连接成功
}
- 查询表
rows, _ := db.Query("select * from city") //获取city表所有数据
var ID, Population int
var Name, CountryCode, District string
for rows.Next() { //循环显示所有的数据
rows.Scan(&ID, &Name, &CountryCode, &District, &Population)
fmt.Println(ID, "--", Name, "--", CountryCode, "--", District, "--", Population)
}
- 全部代码:
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
//"用户名:密码@[连接方式](主机名:端口号)/数据库名"
db, _ := sql.Open("mysql", "root:123456@(localhost)/world") // 设置连接数据库的参数
defer db.Close() //关闭数据库
err := db.Ping() //连接数据库
if err != nil {
fmt.Println("数据库连接失败")
return
} else {
fmt.Println("数据库连接成功")
}
//多行查询
rows, _ := db.Query("select * from city") //获取所有数据
var ID, Population int
var Name, CountryCode, District string
for rows.Next() { //循环显示所有的数据
rows.Scan(&ID, &Name, &CountryCode, &District, &Population)
fmt.Println(ID, "--", Name, "--", CountryCode, "--", District, "--", Population)
}
}
- 拓展
//操作一:执行数据操作语句
sql:="insert into stu values (2,'berry')"
result,_:=db.Exec(sql) //执行SQL语句
n,_:=result.RowsAffected(); //获取受影响的记录数
fmt.Println("受影响的记录数是",n)
//操作二:执行预处理
stu:=[2][2] string{{"3","ketty"},{"4","rose"}}
stmt,_:=db.Prepare("insert into stu values (?,?)") //获取预处理语句对象
for _,s:=range stu{
stmt.Exec(s[0],s[1]) //调用预处理语句
}
//操作三:单行查询
var id,name string
rows:=db.QueryRow("select * from stu where id=4") //获取一行数据
rows.Scan(&id,&name) //将rows中的数据存到id,name中
fmt.Println(id,"--",name)