温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Go 语言如何操作常见的数据库

发布时间:2020-08-08 09:19:46 阅读:212 作者:hj8828 栏目:数据库
亿速云云数据库,读写分离,安全稳定,弹性扩容,低至0.3元/天!! 点击查看>>

使用MySQL数据库

目前 Internet 上流行的网站构架方式是 LAMP/LNMP,其中的 M 即 MySQL, 作为数据库,MySQL 以免费、开源、使用方便为优势成为了很多Web开发的后端数据库存储引擎。

Go中支持MySQL的驱动目前比较多,有如下几种,有些是支持database/sql标准,而有些是采用了自己的实现接口,常用的有如下几种:

  • https://github.com/go-sql-driver/mysql 支持database/sql,全部采用go写。

  • https://github.com/ziutek/mymysql 支持database/sql,也支持自定义的接口,全部采用go写。

  • https://github.com/Philio/GoMySQL 不支持database/sql,自定义接口,全部采用go写。

接下来的例子主要以第一个驱动为例,推荐主要理由是:

  • 这个驱动比较新,维护的比较好;

  • 完全支持database/sql接口;

  • 支持keepalive,保持长连接。

接下来的几个小节里面我们都将采用同一个数据库表结构:数据库test,用户表userinfo,关联用户信息表userdetail。


 1


CREATE

 

TABLE

 

`userinfo`

 (


 2

    

`uid`

 

INT

(

10NOT

 

NULL

 AUTO_INCREMENT,


 3

    

`username`

 

VARCHAR

(

64NULL

 

DEFAULT

 

NULL

,


 4

    

`departname`

 

VARCHAR

(

64NULL

 

DEFAULT

 

NULL

,


 5

    

`created`

 

DATE

 

NULL

 

DEFAULT

 

NULL

,


 6

    PRIMARY 

KEY

 (

`uid`

)


 7

);


 8



 9


CREATE

 

TABLE

 

`userdetail`

 (


10

    

`uid`

 

INT

(

10NOT

 

NULL

 

DEFAULT

 

'0'

,


11

    

`intro`

 

TEXT

 

NULL

,


12

    

`profile`

 

TEXT

 

NULL

,


13

    PRIMARY 

KEY

 (

`uid`

)


14

)


如下示例将示范如何使用database/sql接口对数据库表进行增删改查操作:


 1


// 示例代码11-15



 2


package

 main


 3



 4


import

 (


 5

    

"database/sql"



 6

    

"fmt"



 7

    

//"time"



 8



 9

    _ 

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



10

)


11



12



func

 

main


()


 {


13

    db, err := sql.Open(

"mysql""zuolan:zuolan@/test?charset=utf8"

)


14

    checkErr(err)


15



16

    

//插入数据



17

    stmt, err := db.Prepare(

"INSERT userinfo SET username=?,departname=?,created=?"

)


18

    checkErr(err)


19



20

    res, err := stmt.Exec(

"张三""研发部门""2017-09-09"

)


21

    checkErr(err)


22



23

    id, err := res.LastInsertId()


24

    checkErr(err)


25



26

    fmt.Println(id)


27

    

//更新数据



28

    stmt, err = db.Prepare(

"update userinfo set username=? where uid=?"

)


29

    checkErr(err)


30



31

    res, err = stmt.Exec(

"zuolanupdate"

, id)


32

    checkErr(err)


33



34

    affect, err := res.RowsAffected()


35

    checkErr(err)


36



37

    fmt.Println(affect)


38



39

    

//查询数据



40

    rows, err := db.Query(

"SELECT * FROM userinfo"

)


41

    checkErr(err)


42



43

    

for

 rows.Next() {


44

        

var

 uid 

int



45

        

var

 username 

string



46

        

var

 department 

string



47

        

var

 created 

string



48

        err = rows.Scan(&uid, &username, &department, &created)


49

        checkErr(err)


50

        fmt.Println(uid)


51

        fmt.Println(username)


52

        fmt.Println(department)


53

        fmt.Println(created)


54

    }


55



56

    

//删除数据



57

    stmt, err = db.Prepare(

"delete from userinfo where uid=?"

)


58

    checkErr(err)


59



60

    res, err = stmt.Exec(id)


61

    checkErr(err)


62



63

    affect, err = res.RowsAffected()


64

    checkErr(err)


65



66

    fmt.Println(affect)


67



68

    db.Close()


69



70

}


71



72



func

 

checkErr


(err error)


 {


73

    

if

 err != 

nil

 {


74

        

panic

(err)


75

    }


76

}


通过上面的代码我们可以看出,Go操作MySQL数据库是很方便的。

sql.Open()函数用来打开一个注册过的数据库驱动,go-sql-driver中注册了mysql这个数据库驱动,第二个参数是DSN(Data Source Name),它是go-sql-driver定义的一些数据库链接和配置信息。它支持如下格式:


1


user

@

unix

(/

path

/

to

/

socket

)/

dbname

?

charset

=

utf8



2

user:password@tcp(localhost:

5555

)/dbname?charset=utf8


3

user:password@/dbname


4

user:password@tcp([de:ad:be:ef::ca:fe]:

80

)/dbname


db.Prepare()函数用来返回准备要执行的sql操作,然后返回准备完毕的执行状态。

db.Query()函数用来直接执行Sql返回Rows结果。

stmt.Exec()函数用来执行stmt准备好的SQL语句

我们可以看到我们传入的参数都是=?对应的数据,这样做的方式可以一定程度上防止SQL注入。

使用SQLite数据库

SQLite是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。其特点是高度便携、使用方便、结构紧凑、高效、可靠。与其他数据库管理系统不同,SQLite的安装和运行非常简单,在大多数情况下,只要确保SQLite的二进制文件存在即可开始创建、连接和使用数据库。

如果您正在寻找一个嵌入式数据库项目或解决方案,SQLite是绝对值得考虑。SQLite可以是说开源的Access。

Go支持sqlite的驱动也比较多,但是很多都不支持database/sql接口:

  • https://github.com/mattn/go-sqlite3 支持database/sql接口,基于cgo(关于cgo的知识请参看官方文档)。

  • https://github.com/feyeleanor/gosqlite3 不支持database/sql接口,基于cgo。

  • https://github.com/phf/go-sqlite3 不支持database/sql接口,基于cgo。

目前支持database/sql的SQLite数据库驱动比较少,采用标准接口有利于以后出现更好的驱动的时候做迁移,因此本节后面都采用第一个驱动。

示例的数据库表结构如下所示,相应的建表SQL:


 1


CREATE

 

TABLE

 

`userinfo`

 (


 2

    

`uid`

 

INTEGER

 PRIMARY 

KEY

 AUTOINCREMENT,


 3

    

`username`

 

VARCHAR

(

64NULL

,


 4

    

`departname`

 

VARCHAR

(

64NULL

,


 5

    

`created`

 

DATE

 

NULL



 6

);


 7



 8


CREATE

 

TABLE

 

`userdeatail`

 (


 9

    

`uid`

 

INT

(

10NULL

,


10

    

`intro`

 

TEXT

 

NULL

,


11

    

`profile`

 

TEXT

 

NULL

,


12

    PRIMARY 

KEY

 (

`uid`

)


13

);


看下面Go程序是如何操作数据库表,进行数据增删改查的:


 1


// 示例代码11-16



 2


package

 main


 3



 4


import

 (


 5

    

"database/sql"



 6

    

"fmt"



 7

    

"time"



 8



 9

    _ 

"github.com/mattn/go-sqlite3"



10

)


11



12



func

 

main


()


 {


13

    db, err := sql.Open(

"sqlite3""./demo.db"

)


14

    checkErr(err)


15



16

    

//插入数据



17

    stmt, err := db.Prepare(

"INSERT INTO userinfo(username, departname, created) values(?,?,?)"

)


18

    checkErr(err)


19



20

    res, err := stmt.Exec(

"张三""研发部门""2017-09-09"

)


21

    checkErr(err)


22



23

    id, err := res.LastInsertId()


24

    checkErr(err)


25



26

    fmt.Println(id)


27

    

//更新数据



28

    stmt, err = db.Prepare(

"update userinfo set username=? where uid=?"

)


29

    checkErr(err)


30



31

    res, err = stmt.Exec(

"zuolanupdate"

, id)


32

    checkErr(err)


33



34

    affect, err := res.RowsAffected()


35

    checkErr(err)


36



37

    fmt.Println(affect)


38



39

    

//查询数据



40

    rows, err := db.Query(

"SELECT * FROM userinfo"

)


41

    checkErr(err)


42



43

    

for

 rows.Next() {


44

        

var

 uid 

int



45

        

var

 username 

string



46

        

var

 department 

string



47

        

var

 created time.Time


48

        err = rows.Scan(&uid, &username, &department, &created)


49

        checkErr(err)


50

        fmt.Println(uid)


51

        fmt.Println(username)


52

        fmt.Println(department)


53

        fmt.Println(created)


54

    }


55



56

    

//删除数据



57

    stmt, err = db.Prepare(

"delete from userinfo where uid=?"

)


58

    checkErr(err)


59



60

    res, err = stmt.Exec(id)


61

    checkErr(err)


62



63

    affect, err = res.RowsAffected()


64

    checkErr(err)


65



66

    fmt.Println(affect)


67



68

    db.Close()


69



70

}


71



72



func

 

checkErr


(err error)


 {


73

    

if

 err != 

nil

 {


74

        

panic

(err)


75

    }


76

}


我们可以看到上面的代码和MySQL例子里面的代码几乎是一模一样的,唯一改变的就是导入的驱动改变了,然后调用sql.Open是采用了SQLite的方式打开。

使用PostgreSQL数据库

PostgreSQL是一个自由的对象-关系数据库服务器(数据库管理系统),它在灵活的BSD风格许可证下发行。它提供了相对其他开放源代码数据库系统(比如MySQL和Firebird),和对专有系统比如Oracle、Sybase、IBM的DB2和Microsoft SQL Server的一种选择。

PostgreSQL和MySQL比较,它更加庞大一点,因为它是用来替代Oracle而设计的。所以在企业应用中采用PostgreSQL是一个明智的选择。

MySQL被Oracle收购之后正在逐步的封闭(自MySQL 5.5.31以后的所有版本将不再遵循GPL协议),鉴于此,将来我们也许会选择PostgreSQL而不是MySQL作为项目的后端数据库。

Go实现的支持PostgreSQL的驱动也很多,因为国外很多人在开发中使用了这个数据库。

  • https://github.com/lib/pq 支持database/sql驱动,纯Go写的;

  • https://github.com/jbarham/gopgsqldriver 支持database/sql驱动,纯Go写的;

  • https://github.com/lxn/go-pgsql 支持database/sql驱动,纯Go写的。

在下面的示例中采用第一个驱动,因为它目前使用的人最多,在Github上也比较活跃。

数据库建表语句:


 1


CREATE

 

TABLE

 userinfo


 2

(


 3

    uid 

serial

 

NOT

 

NULL

,


 4

    username 

character

 

varying

(

100NOT

 

NULL

,


 5

    departname 

character

 

varying

(

500NOT

 

NULL

,


 6

    Created 

date

,


 7

    

CONSTRAINT

 userinfo_pkey PRIMARY 

KEY

 (uid)


 8

)


 9


WITH

 (OIDS=

FALSE

);


10



11


CREATE

 

TABLE

 userdeatail


12

(


13

    uid 

integer

,


14

    intro 

character

 

varying

(

100

),


15

    profile 

character

 

varying

(

100

)


16

)


17


WITH

(OIDS=

FALSE

);


看下面这个Go如何操作数据库表,进行数据的增删改查:


 1


// 示例代码11-17



 2


package

 main


 3



 4


import

 (


 5

    

"database/sql"



 6

    

"fmt"



 7



 8

    _ 

"github.com/lib/pq"



 9

)


10



11



func

 

main


()


 {


12

    db, err := sql.Open(

"postgres""user=zuolan password=zuolan dbname=test sslmode=disable"

)


13

    checkErr(err)


14



15

    

//插入数据



16

    stmt, err := db.Prepare(

"INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) RETURNING uid"

)


17

    checkErr(err)


18



19

    res, err := stmt.Exec(

"张三""研发部门""2017-09-09"

)


20

    checkErr(err)


21



22

    

// pg不支持这个函数,因为他没有类似MySQL的自增ID



23

    

// id, err := res.LastInsertId()



24

    

// checkErr(err)



25

    

// fmt.Println(id)



26



27

    

var

 lastInsertId 

int



28

    err = db.QueryRow(

"INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) returning uid;""zuolan""研发部门""2017-09-09"

).Scan(&lastInsertId)


29

    checkErr(err)


30

    fmt.Println(

"最后插入id ="

, lastInsertId)


31



32



33

    

//更新数据



34

    stmt, err = db.Prepare(

"update userinfo set username=$1 where uid=$2"

)


35

    checkErr(err)


36



37

    res, err = stmt.Exec(

"zuolanupdate"1

)


38

    checkErr(err)


39



40

    affect, err := res.RowsAffected()


41

    checkErr(err)


42



43

    fmt.Println(affect)


44



45

    

//查询数据



46

    rows, err := db.Query(

"SELECT * FROM userinfo"

)


47

    checkErr(err)


48



49

    

for

 rows.Next() {


50

        

var

 uid 

int



51

        

var

 username 

string



52

        

var

 department 

string



53

        

var

 created 

string



54

        err = rows.Scan(&uid, &username, &department, &created)


55

        checkErr(err)


56

        fmt.Println(uid)


57

        fmt.Println(username)


58

        fmt.Println(department)


59

        fmt.Println(created)


60

    }


61



62

    

//删除数据



63

    stmt, err = db.Prepare(

"delete from userinfo where uid=$1"

)


64

    checkErr(err)


65



66

    res, err = stmt.Exec(

1

)


67

    checkErr(err)


68



69

    affect, err = res.RowsAffected()


70

    checkErr(err)


71



72

    fmt.Println(affect)


73



74

    db.Close()


75



76

}


77



78



func

 

checkErr


(err error)


 {


79

    

if

 err != 

nil

 {


80

        

panic

(err)


81

    }


82

}


从上面的代码我们可以看到,PostgreSQL是通过 1, 2这种方式来指定要传递的参数,而不是MySQL中的?,另外在sql.Open中的dsn信息的格式也与MySQL的驱动中的dsn格式不一样,所以在使用时请注意它们的差异。

还有pg不支持LastInsertId函数,因为PostgreSQL内部没有实现类似MySQL的自增ID返回,其他的代码几乎是一模一样。

NoSQL数据库操作

NoSQL(Not Only SQL),指的是非关系型的数据库。随着Web2.0的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。

而Go语言作为21世纪的C语言,对NOSQL的支持也是很好,目前流行的NOSQL主要有redismongoDB、Cassandra和Membase等。这些数据库都有高性能、高并发读写等特点,目前已经广泛应用于各种应用中。

1. Redis

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。

目前应用redis最广泛的应该是新浪微博平台,其次还有Facebook收购的图片社交网站instagram。Go目前支持redis的驱动有如下:

  • https://github.com/garyburd/redigo

  • https://github.com/go-redis/redis

  • https://github.com/hoisie/redis

  • https://github.com/alphazero/Go-Redis

  • https://github.com/simonz05/godis

推荐使用第一个,用法上和上面驱动没有太大区别,限于篇幅不再展开。

2. mongoDB

MongoDB是一个高性能,开源,无模式的文档型数据库,是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,采用的是类似json的bjson格式来存储数据,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

目前Go支持mongoDB最好的驱动就是mgo(http://labix.org/mgo),这个驱动目前最有可能成为官方的pkg。安装mgo的命令为:

1go get gopkg.in/mgo.v2

亿速云「云数据库 MySQL」免部署即开即用,比自行安装部署数据库高出1倍以上的性能,双节点冗余防止单节点故障,数据自动定期备份随时恢复。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:http://blog.itpub.net/31554484/viewspace-2215655/

AI

开发者交流群×