您好,登錄后才能下訂單哦!
目前 Internet 上流行的網(wǎng)站構(gòu)架方式是 LAMP/LNMP,其中的 M 即 MySQL, 作為數(shù)據(jù)庫,MySQL 以免費(fèi)、開源、使用方便為優(yōu)勢成為了很多Web開發(fā)的后端數(shù)據(jù)庫存儲引擎。
Go中支持MySQL的驅(qū)動目前比較多,有如下幾種,有些是支持database/sql標(biāo)準(zhǔn),而有些是采用了自己的實(shí)現(xiàn)接口,常用的有如下幾種:
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寫。
接下來的例子主要以第一個驅(qū)動為例,推薦主要理由是:
這個驅(qū)動比較新,維護(hù)的比較好;
完全支持database/sql接口;
支持keepalive,保持長連接。
接下來的幾個小節(jié)里面我們都將采用同一個數(shù)據(jù)庫表結(jié)構(gòu):數(shù)據(jù)庫test,用戶表userinfo,關(guān)聯(lián)用戶信息表userdetail。
1
CREATE
TABLE
`userinfo`
(
2
`uid`
INT
(
10
)
NOT
NULL
AUTO_INCREMENT,
3
`username`
VARCHAR
(
64
)
NULL
DEFAULT
NULL
,
4
`departname`
VARCHAR
(
64
)
NULL
DEFAULT
NULL
,
5
`created`
DATE
NULL
DEFAULT
NULL
,
6
PRIMARY
KEY
(
`uid`
)
7
);
8
9
CREATE
TABLE
`userdetail`
(
10
`uid`
INT
(
10
)
NOT
NULL
DEFAULT
'0'
,
11
`intro`
TEXT
NULL
,
12
`profile`
TEXT
NULL
,
13
PRIMARY
KEY
(
`uid`
)
14
)
如下示例將示范如何使用database/sql接口對數(shù)據(jù)庫表進(jìn)行增刪改查操作:
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
//插入數(shù)據(jù)
17
stmt, err := db.Prepare(
"INSERT userinfo SET username=?,departname=?,created=?"
)
18
checkErr(err)
19
20
res, err := stmt.Exec(
"張三"
,
"研發(fā)部門"
,
"2017-09-09"
)
21
checkErr(err)
22
23
id, err := res.LastInsertId()
24
checkErr(err)
25
26
fmt.Println(id)
27
//更新數(shù)據(jù)
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
//查詢數(shù)據(jù)
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
//刪除數(shù)據(jù)
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數(shù)據(jù)庫是很方便的。
sql.Open()函數(shù)用來打開一個注冊過的數(shù)據(jù)庫驅(qū)動,go-sql-driver中注冊了mysql這個數(shù)據(jù)庫驅(qū)動,第二個參數(shù)是DSN(Data Source Name),它是go-sql-driver定義的一些數(shù)據(jù)庫鏈接和配置信息。它支持如下格式:
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()函數(shù)用來返回準(zhǔn)備要執(zhí)行的sql操作,然后返回準(zhǔn)備完畢的執(zhí)行狀態(tài)。
db.Query()函數(shù)用來直接執(zhí)行Sql返回Rows結(jié)果。
stmt.Exec()函數(shù)用來執(zhí)行stmt準(zhǔn)備好的SQL語句
我們可以看到我們傳入的參數(shù)都是=?對應(yīng)的數(shù)據(jù),這樣做的方式可以一定程度上防止SQL注入。
SQLite是一個開源的嵌入式關(guān)系數(shù)據(jù)庫,實(shí)現(xiàn)自包容、零配置、支持事務(wù)的SQL數(shù)據(jù)庫引擎。其特點(diǎn)是高度便攜、使用方便、結(jié)構(gòu)緊湊、高效、可靠。與其他數(shù)據(jù)庫管理系統(tǒng)不同,SQLite的安裝和運(yùn)行非常簡單,在大多數(shù)情況下,只要確保SQLite的二進(jìn)制文件存在即可開始創(chuàng)建、連接和使用數(shù)據(jù)庫。
如果您正在尋找一個嵌入式數(shù)據(jù)庫項(xiàng)目或解決方案,SQLite是絕對值得考慮。SQLite可以是說開源的Access。
Go支持sqlite的驅(qū)動也比較多,但是很多都不支持database/sql接口:
https://github.com/mattn/go-sqlite3 支持database/sql接口,基于cgo(關(guān)于cgo的知識請參看官方文檔)。
https://github.com/feyeleanor/gosqlite3 不支持database/sql接口,基于cgo。
https://github.com/phf/go-sqlite3 不支持database/sql接口,基于cgo。
目前支持database/sql的SQLite數(shù)據(jù)庫驅(qū)動比較少,采用標(biāo)準(zhǔn)接口有利于以后出現(xiàn)更好的驅(qū)動的時候做遷移,因此本節(jié)后面都采用第一個驅(qū)動。
示例的數(shù)據(jù)庫表結(jié)構(gòu)如下所示,相應(yīng)的建表SQL:
1
CREATE
TABLE
`userinfo`
(
2
`uid`
INTEGER
PRIMARY
KEY
AUTOINCREMENT,
3
`username`
VARCHAR
(
64
)
NULL
,
4
`departname`
VARCHAR
(
64
)
NULL
,
5
`created`
DATE
NULL
6
);
7
8
CREATE
TABLE
`userdeatail`
(
9
`uid`
INT
(
10
)
NULL
,
10
`intro`
TEXT
NULL
,
11
`profile`
TEXT
NULL
,
12
PRIMARY
KEY
(
`uid`
)
13
);
看下面Go程序是如何操作數(shù)據(jù)庫表,進(jìn)行數(shù)據(jù)增刪改查的:
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
//插入數(shù)據(jù)
17
stmt, err := db.Prepare(
"INSERT INTO userinfo(username, departname, created) values(?,?,?)"
)
18
checkErr(err)
19
20
res, err := stmt.Exec(
"張三"
,
"研發(fā)部門"
,
"2017-09-09"
)
21
checkErr(err)
22
23
id, err := res.LastInsertId()
24
checkErr(err)
25
26
fmt.Println(id)
27
//更新數(shù)據(jù)
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
//查詢數(shù)據(jù)
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
//刪除數(shù)據(jù)
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例子里面的代碼幾乎是一模一樣的,唯一改變的就是導(dǎo)入的驅(qū)動改變了,然后調(diào)用sql.Open是采用了SQLite的方式打開。
PostgreSQL是一個自由的對象-關(guān)系數(shù)據(jù)庫服務(wù)器(數(shù)據(jù)庫管理系統(tǒng)),它在靈活的BSD風(fēng)格許可證下發(fā)行。它提供了相對其他開放源代碼數(shù)據(jù)庫系統(tǒng)(比如MySQL和Firebird),和對專有系統(tǒng)比如Oracle、Sybase、IBM的DB2和Microsoft SQL Server的一種選擇。
PostgreSQL和MySQL比較,它更加龐大一點(diǎn),因?yàn)樗怯脕硖娲鶲racle而設(shè)計(jì)的。所以在企業(yè)應(yīng)用中采用PostgreSQL是一個明智的選擇。
MySQL被Oracle收購之后正在逐步的封閉(自MySQL 5.5.31以后的所有版本將不再遵循GPL協(xié)議),鑒于此,將來我們也許會選擇PostgreSQL而不是MySQL作為項(xiàng)目的后端數(shù)據(jù)庫。
Go實(shí)現(xiàn)的支持PostgreSQL的驅(qū)動也很多,因?yàn)閲夂芏嗳嗽陂_發(fā)中使用了這個數(shù)據(jù)庫。
https://github.com/lib/pq 支持database/sql驅(qū)動,純Go寫的;
https://github.com/jbarham/gopgsqldriver 支持database/sql驅(qū)動,純Go寫的;
https://github.com/lxn/go-pgsql 支持database/sql驅(qū)動,純Go寫的。
在下面的示例中采用第一個驅(qū)動,因?yàn)樗壳笆褂玫娜俗疃?,在Github上也比較活躍。
數(shù)據(jù)庫建表語句:
1
CREATE
TABLE
userinfo
2
(
3
uid
serial
NOT
NULL
,
4
username
character
varying
(
100
)
NOT
NULL
,
5
departname
character
varying
(
500
)
NOT
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如何操作數(shù)據(jù)庫表,進(jìn)行數(shù)據(jù)的增刪改查:
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
//插入數(shù)據(jù)
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(
"張三"
,
"研發(fā)部門"
,
"2017-09-09"
)
20
checkErr(err)
21
22
// pg不支持這個函數(shù),因?yàn)樗麤]有類似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"
,
"研發(fā)部門"
,
"2017-09-09"
).Scan(&lastInsertId)
29
checkErr(err)
30
fmt.Println(
"最后插入id ="
, lastInsertId)
31
32
33
//更新數(shù)據(jù)
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
//查詢數(shù)據(jù)
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
//刪除數(shù)據(jù)
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這種方式來指定要傳遞的參數(shù),而不是MySQL中的?,另外在sql.Open中的dsn信息的格式也與MySQL的驅(qū)動中的dsn格式不一樣,所以在使用時請注意它們的差異。
還有pg不支持LastInsertId函數(shù),因?yàn)镻ostgreSQL內(nèi)部沒有實(shí)現(xiàn)類似MySQL的自增ID返回,其他的代碼幾乎是一模一樣。
NoSQL(Not Only SQL),指的是非關(guān)系型的數(shù)據(jù)庫。隨著Web2.0的興起,傳統(tǒng)的關(guān)系數(shù)據(jù)庫在應(yīng)付Web2.0網(wǎng)站,特別是超大規(guī)模和高并發(fā)的SNS類型的Web2.0純動態(tài)網(wǎng)站已經(jīng)顯得力不從心,暴露了很多難以克服的問題,而非關(guān)系型的數(shù)據(jù)庫則由于其本身的特點(diǎn)得到了非常迅速的發(fā)展。
而Go語言作為21世紀(jì)的C語言,對NOSQL的支持也是很好,目前流行的NOSQL主要有redis、mongoDB、Cassandra和Membase等。這些數(shù)據(jù)庫都有高性能、高并發(fā)讀寫等特點(diǎn),目前已經(jīng)廣泛應(yīng)用于各種應(yīng)用中。
redis是一個key-value存儲系統(tǒng)。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)和zset(有序集合)。
目前應(yīng)用redis最廣泛的應(yīng)該是新浪微博平臺,其次還有Facebook收購的圖片社交網(wǎng)站instagram。Go目前支持redis的驅(qū)動有如下:
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
推薦使用第一個,用法上和上面驅(qū)動沒有太大區(qū)別,限于篇幅不再展開。
MongoDB是一個高性能,開源,無模式的文檔型數(shù)據(jù)庫,是一個介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫當(dāng)中功能最豐富,最像關(guān)系數(shù)據(jù)庫的。他支持的數(shù)據(jù)結(jié)構(gòu)非常松散,采用的是類似json的bjson格式來存儲數(shù)據(jù),因此可以存儲比較復(fù)雜的數(shù)據(jù)類型。Mongo最大的特點(diǎn)是他支持的查詢語言非常強(qiáng)大,其語法有點(diǎn)類似于面向?qū)ο蟮牟樵冋Z言,幾乎可以實(shí)現(xiàn)類似關(guān)系數(shù)據(jù)庫單表查詢的絕大部分功能,而且還支持對數(shù)據(jù)建立索引。
目前Go支持mongoDB最好的驅(qū)動就是mgo(http://labix.org/mgo),這個驅(qū)動目前最有可能成為官方的pkg。安裝mgo的命令為:
1go get gopkg.in/mgo.v2
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。