原文地址: Go 操作 MySql 数据库的方式
使用 Go 操作 MySQL 等数据库,一般有两种方式:一是使用 database/sql 接口,直接在代码里硬编码 sql 语句;二是使用 gorm,即对象关系映射的方式在代码里抽象的操作数据库。一般推荐使用第二种方式。
Go 没有内置的驱动支持任何数据库,但是 Go 定义了 database/sql 接口,用户可以基于驱动接口开发相应数据库的驱动。但缺点是,直接用 github.com/go-sql-driver/mysql 访问数据库都是直接写 sql,取出结果然后自己拼成对象,使用上面不是很方便,可读性也不好。
package main
import (
"database/sql"
"fmt"
\_ "github.com/go-sql-driver/mysql"
"time"
)
//数据库连接信息
const (
USERNAME = "root"
PASSWORD = "123456"
NETWORK = "tcp"
SERVER = "127.0.0.1"
PORT = 3306
DATABASE = "test"
)
//user表结构体定义
type User struct {
Id int \`json:"id" form:"id"\`
Username string \`json:"username" form:"username"\`
Password string \`json:"password" form:"password"\`
Status int \`json:"status" form:"status"\` // 0 正常状态, 1删除
Createtime int64 \`json:"createtime" form:"createtime"\`
}
func main() {
conn := fmt.Sprintf("%s:%s@%s(%s:%d)/%s",USERNAME, PASSWORD, NETWORK, SERVER, PORT, DATABASE)
DB, err := sql.Open("mysql", conn)
if err != nil {
fmt.Println("connection to mysql failed:", err)
return
}
DB.SetConnMaxLifetime(100\*time.Second) //最大连接周期,超时的连接就close
DB.SetMaxOpenConns(100) //设置最大连接数
CreateTable(DB)
InsertData(DB)
QueryOne(DB)
QueryMulti(DB)
UpdateData(DB)
DeleteData(DB)
}
func CreateTable(DB \*sql.DB) {
sql := \`CREATE TABLE IF NOT EXISTS users(
id INT(4) PRIMARY KEY AUTO\_INCREMENT NOT NULL,
username VARCHAR(64),
password VARCHAR(64),
status INT(4),
createtime INT(10)
); \`
if \_, err := DB.Exec(sql); err != nil {
fmt.Println("create table failed:", err)
return
}
fmt.Println("create table successd")
}
//插入数据
func InsertData(DB \*sql.DB) {
result,err := DB.Exec("insert INTO users(username,password) values(?,?)","test","123456")
if err != nil{
fmt.Printf("Insert data failed,err:%v", err)
return
}
lastInsertID,err := result.LastInsertId() //获取插入数据的自增ID
if err != nil {
fmt.Printf("Get insert id failed,err:%v", err)
return
}
fmt.Println("Insert data id:", lastInsertID)
rowsaffected,err := result.RowsAffected() //通过RowsAffected获取受影响的行数
if err != nil {
fmt.Printf("Get RowsAffected failed,err:%v",err)
return
}
fmt.Println("Affected rows:", rowsaffected)
}
//查询单行
func QueryOne(DB \*sql.DB) {
user := new(User) //用new()函数初始化一个结构体对象
row := DB.QueryRow("select id,username,password from users where id=?", 1)
//row.scan中的字段必须是按照数据库存入字段的顺序,否则报错
if err := row.Scan(&user.Id,&user.Username,&user.Password); err != nil {
fmt.Printf("scan failed, err:%v\\n", err)
return
}
fmt.Println("Single row data:", \*user)
}
//查询多行
func QueryMulti(DB \*sql.DB) {
user := new(User)
rows, err := DB.Query("select id,username,password from users where id = ?", 2)
defer func() {
if rows != nil {
rows.Close() //关闭掉未scan的sql连接
}
}()
if err != nil {
fmt.Printf("Query failed,err:%v\\n", err)
return
}
for rows.Next() {
err = rows.Scan(&user.Id, &user.Username, &user.Password) //不scan会导致连接不释放
if err != nil {
fmt.Printf("Scan failed,err:%v\\n", err)
return
}
fmt.Println("scan successd:", \*user)
}
}
//更新数据
func UpdateData(DB \*sql.DB){
result,err := DB.Exec("UPDATE users set password=? where id=?","111111",1)
if err != nil{
fmt.Printf("Insert failed,err:%v\\n", err)
return
}
fmt.Println("update data successd:", result)
rowsaffected,err := result.RowsAffected()
if err != nil {
fmt.Printf("Get RowsAffected failed,err:%v\\n",err)
return
}
fmt.Println("Affected rows:", rowsaffected)
}
//删除数据
func DeleteData(DB \*sql.DB){
result,err := DB.Exec("delete from users where id=?",1)
if err != nil{
fmt.Printf("Insert failed,err:%v\\n",err)
return
}
fmt.Println("delete data successd:", result)
rowsaffected,err := result.RowsAffected()
if err != nil {
fmt.Printf("Get RowsAffected failed,err:%v\\n",err)
return
}
fmt.Println("Affected rows:", rowsaffected)
}
GORM(Object Relation Mapping),即 Go 语言中的对象关系映射,实际上就是对数据库的操作进行封装,对上层开发人员屏蔽数据操作的细节,开发人员看到的就是一个个对象,大大简化了开发工作,提高了生产效率。如 GORM 结合 Gin 等服务端框架使用可以开发出丰富的 Rest API 等。
通过非常简短的代码, 就可以实现功能强大的 restful 接口, go 语言的优势也是非常明显的. 关于 gin 和 gorm 还有更加深入的内容. 掌握好这两个工具可以轻松的构建 web 应用。