内容简介:使用Go操作MySQL等数据库,一般有两种方式:一是使用database/sql接口,直接在代码里硬编码sql语句;二是使用gorm,即对象关系映射的方式在代码里抽象的操作数据库。一般推荐使用第二种方式。Go没有内置的驱动支持任何数据库,但是Go定义了database/sql接口,用户可以基于驱动接口开发相应数据库的驱动。但缺点是,直接用 github.com/go-sql-driver/mysql 访问数据库都是直接写 sql,取出结果然后自己拼成对象,使用上面不是很方便,可读性也不好。下载包
使用 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 //用户查找
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Keepalived+expect方式实现Redis主从高可用实际操作
- Dlang、Rust 以及 Golang 数据库操作方式对比
- 实例讲解Springboot整合MongoDB进行CRUD操作的两种方式
- iOS狂暴之路–两种布局方式操作详解(xib文件和代码编写)
- PHP实现定时任务(非linux-shell方式,与操作系统无关)
- Java8中创建Stream 流的四种方式以及 Stream 中间操作
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
图论算法理论、实现及应用
王桂平//王衍//任嘉辰 / 北京大学 / 2011-1 / 54.00元
《图论算法理论、实现及应用》系统地介绍了图论算法理论,并选取经典的ACM/ICPC竞赛题目为例题阐述图论算法思想,侧重于图论算法的程序实现及应用。《图论算法理论、实现及应用》第1章介绍图的基本概念和图的两种存储表示方法:邻接矩阵和邻接表,第2~9章分别讨论图的遍历与活动网络问题,树与图的生成树,最短路径问题,可行遍性问题,网络流问题,支配集、覆盖集、独立集与匹配,图的连通性问题,平面图及图的着色问......一起来看看 《图论算法理论、实现及应用》 这本书的介绍吧!