go mysql 映射_Go操作MySql数据库的方式

使用 Go 操作 MySQL 等数据库,一般有两种方式:一是使用database/sql接口,直接在代码里硬编码sql语句;二是使用gorm,即对象关系映射的方式在代码里抽象的操作数据库。一般推荐使用第二种方式。

使用database/sql接口

Go没有内置的驱动支持任何数据库,但是Go定义了database/sql接口,用户可以基于驱动接口开发相应 数据库 的驱动。但缺点是,直接用 github.com/go-sql-driver/mysql 访问数据库都是直接写 sql,取出结果然后自己拼成对象,使用上面不是很方便,可读性也不好。

下载包

go get github.com/go-sql-driver/mysql

安装好 mysql 驱动之后,我们创建一张user表,并执行CRUD操作(增、删、改、查)。代码如下所示:

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)

}

执行程序,输出结果如下所示:

create table successd

Insert data id: 1

Affected rows: 1

Single row data: {1 test 123456 0 0}

update data successd: {0xc0000a0000 0xc000010280}

Affected rows: 1

delete data successd: {0xc0000a0000 0xc0000102b0}

Affected rows: 1

OK,到这里大家是不是觉得这种实现方式很繁琐,假如要修改某个sql语句需要在代码中修改,这样很麻烦,代码设计也比较糟糕。因此这种方式并不推荐使用。

使用GORM

GORM(Object Relation Mapping),即Go语言中的对象关系映射,实际上就是对数据库的操作进行封装,对上层开发人员屏蔽数据操作的细节,开发人员看到的就是一个个对象,大大简化了开发工作,提高了生产效率。如GORM结合Gin等服务端框架使用可以开发出丰富的Rest API等。

首先,下载包

go get github.com/jinzhu/gorm

使用Go的Gin框架和Gorm开发简单的CRUD API,代码如下

package main

import (

"fmt"

"github.com/gin-gonic/gin"

"github.com/jinzhu/gorm"

_ "github.com/jinzhu/gorm/dialects/mysql"

)

var MysqlDB *gorm.DB

type User struct {

Id int `gorm:"size:11;primary_key;AUTO_INCREMENT;not null" json:"id"`

Age int `gorm:"size:11;DEFAULT NULL" json:"age"`

Name string `gorm:"size:255;DEFAULT NULL" json:"name"`

//gorm后添加约束,json后为对应mysql里的字段

}

func main() {

MysqlDB, err := gorm.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")

if err != nil {

fmt.Println("failed to connect database:", err)

return

}

fmt.Println("connect database success")

MysqlDB.SingularTable(true)

MysqlDB.AutoMigrate(&User{}) //自动建表

fmt.Println("create table success")

defer MysqlDB.Close()

Router()

}

func Router() {

router := gin.Default()

router.GET("/user/init", InitPage)

router.POST("/user/create", CreateUser)

router.GET("/user/list", ListUser)

router.POST("/user/update", UpdateUser)

router.GET("/user/find", GetUser)

router.Run(":8080")

//API接口

}

func InitPage(c *gin.Context) {

c.JSON(200, gin.H{

"message": "pong",

})

}

func CreateUser(c *gin.Context) {

var user User

c.BindJSON(&user) //使用bindJSON填充对象

MysqlDB.Create(&user) //创建对象

c.JSON(200, &user) //返回页面

}

func UpdateUser(c *gin.Context) {

var user User

id := c.PostForm("id") //post方法取相应字段

err := MysqlDB.First(&user, id).Error //数据库查找主键=ID的第一行

if err != nil {

c.AbortWithStatus(404)

fmt.Println(err.Error())

} else {

c.BindJSON(&user)

MysqlDB.Save(&user) //提交更改

c.JSON(200, &user)

}

}

func ListUser(c *gin.Context) {

var user []User

line := c.Query("line")

MysqlDB.Limit(line).Find(&user) //限制查找前line行

c.JSON(200, &user)

}

func GetUser(c *gin.Context) {

id := c.Query("id")

var user User

err := MysqlDB.First(&user, id).Error

if err != nil {

c.AbortWithStatus(404)

fmt.Println(err.Error())

} else {

c.JSON(200, &user)

}

}

这样,我们就定义了如下几个API接口:

http://127.0.0.1:8080/user/init //用户初始化

http://127.0.0.1:8080/user/create //用户创建

http://127.0.0.1:8080/user/list //用户列出

http://127.0.0.1:8080/user/update //用户更新

http://127.0.0.1:8080/user/find //用户查找

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值