GoLang—MySQL数据库操作

Go标准库中没有数据库驱动,如果实现数据库连接与操作,参见获取第三方的数据库驱动。本文以MySQL为例,我们使用go-sql-driver实现数据库的连接和操作,首先在CMD窗口下安装驱动go-sql-driver,指令如下。

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

数据库驱动安装成功后,在GoLand(ide)中使用go-sql-driver实现数据库的连接和操作,实现方式首先连接MySQL的某个数据库,生成数据库对象db,然后使用数据库对象db对数据表实现怎删改查操作。

数据查询

go-sql-driver提供2种数据查询方式:Query和QueryRow。Query是查询多行数据,也可以查询单行数据,适用范围较广;QueryRow只能查询单行数据,该对象能调用的方法较少,局限性较大。不管Query或QueryRow,两者只查询数据表的数据,如果想将数据表的字段与数据一一对应,需要我们编写函数方法实现,废话不多说,直接看代码。

package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

func GetAll(rows *sql.Rows) []map[string]string {
	// 判断传入的查询结果是否为nil
	if rows == nil {
		return nil
	}
	// 定义返回值的数据类型(定义为数组,元素类型为映射,映射的数据为字符串类型)
	var result []map[string]string
	// 获取查询结果rows的列名(即字段名)
	cols, _ := rows.Columns()
	// 定义数组byte
	rawResult := make([][]byte, len(cols))
	// 定义数组dest
	dest := make([]interface{}, len(cols))
	// 将byte数组的内存地址对应分配给dest
	for i, _ := range rawResult {
		dest[i] = &rawResult[i]
	}

	// 遍历每行数据
	for rows.Next()  {
		// 将每行的数据分别存入数组dest
		// 由于数组dest和数组byte的内存地址是相同的
		// 因此两个数组的数据也是相同,只不过两个数组的每个元素的数据格式不同
		rows.Scan(dest...)
		// 根据列的个数定义相应的映射对象sresult
		sresult := make(map[string]string, len(cols))
		// 将当前数据写入映射对象sresult
		for i, raw := range rawResult {
			if raw == nil {
				sresult[cols[i]] = ""
			} else {
				sresult[cols[i]] = string(raw)
			}
		}
		// 将数据写入数组result
		result = append(result, sresult)
	}
	// 将数组result作为返回值
	return result
}



func main(){
	// 连接MySQL数据库
	db, _ := sql.Open("mysql", "root:1234@tcp(127.0.0.1:3306)/music_db?charset=utf8")
	// 查询方式一,先使用Prepare再使用Query或QueryRow
	p , _ := db.Prepare("select * from index_song")
	rows, _ := p.Query()
	// 查询方式二,直接使用Query或QueryRow
	//rows, _ := db.Query("select * from index_song")
	s2 := GetAll(rows)
	for _, v := range s2{
		// 将映射对象转化JSON数据
		mjson, _ :=json.Marshal(v)
		mString :=string(mjson)
		fmt.Println(mString)
	}
	// 查询方式三,查询单条数据
	// 适合单条数据的某些字段,如果查询全部字段,建议使用Query
	row := db.QueryRow("select name,album from index_song where id=1")
	var name,album string
	row.Scan(&name,&album)
	fmt.Println(name,album)
}


上述代码中,涉及了两个Go的基础语法,下划线(_)和三个点(…),本文不再详细讲述语法知识,读者可以点击相关链接查看。
函数方法GetAll是将Query查询对象rows作为函数参数,函数返回值result为数组类型,数组元素的数据类型为映射对象。函数首先从查询对象rows获取数据表的字段名,生成对象cols,将对象cols的字段名作为返回值result的映射对象的key,而数据表的数据作为映射对象的value。具体的实现过程不过多讲述,详细可看代码注释。

数据增改删

数据的增改删操作主要由Exec方法实现,实现方法较为简单,直接看到代码即可理解

package main

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

func main(){
	// 连接MySQL数据库
	db, _ := sql.Open("mysql", "root:1234@tcp(127.0.0.1:3306)/music_db?charset=utf8")
	// 新增数据
	ret, _ := db.Exec("insert into index_label(id,name) values(15,'测试测试')")
	// LastInsertId是获取数据新增后的ID
	insID, _ := ret.LastInsertId()
	fmt.Println(insID)
	// 修改数据
	ret2, _ := db.Exec("update index_label set name= 'GOGO' where id = ?", 15)
	// RowsAffected是获取已被修改的数据总数
	aff_nums, _ := ret2.RowsAffected()
	fmt.Println(aff_nums)
	// 删除数据
	ret3, _ := db.Exec("delete from index_label where id = ?",15)
	delNums, _ := ret3.RowsAffected()
	fmt.Println(delNums)
}


事务

事务由Begin函数方法实现,只需在数据库连接对象调用Begin函数方法即可,然后由Begin函数方法生成的对象执行数据操作即可,可以根据执行结果判断当前事务是否执行或回滚,详细代码如下。

package main

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

func main(){
	// 连接MySQL数据库
	db, _ := sql.Open("mysql", "root:1234@tcp(127.0.0.1:3306)/music_db?charset=utf8")
	//开启事务
	tx, _ := db.Begin()
	//id为1的price+1,id为2的price-1
	ret4, _ := tx.Exec("update index_label set name = '测试事务1' where id = ?", 10)
	ret5, _ := tx.Exec("update index_label set name = '测试事务2' where id = ?", 2)

	//如果id不存在,受影响行数则为0
	//接收影响行数,为0则失败
	updNums1, _ := ret4.RowsAffected()
	updNums2, _ := ret5.RowsAffected()
	if updNums1 > 0 && updNums2 > 0 { //只有两条更新同时成功,那么才提交
		tx.Commit() //提交事务
		fmt.Println("Success")
	} else { //否则回滚
		tx.Rollback() //回退事务
		fmt.Println("Fail")
	}
}


综合上述,本博文讲述了如何使用go-sql-driver实现数据库MySQL数据库操作,下一节将讲述如何使用ORM框架实现数据库操作。

你可能感兴趣的:(爬虫,数据处理,GoLang)