一文學會Go語言數據庫操作

sicoly 7年前發布 | 17K 次閱讀 數據庫 Go語言 Google Go/Golang開發

對許多 Web 應用程序而言,數據庫都是其核心所在。數據庫幾乎可以用來存儲想查詢和修改的任何信息,比如用戶信息、產品目錄或者新聞列表等。

數據庫是Web編程不可或缺的主題。這里我們就來看一下如何用 Go 語言操作不同的數據庫。

database/sql 接口

Go 語言不同于 PHP,它沒有官方提供任何數據庫驅動,而是為開發者定義了一組標準接口。提供數據庫服務的開發者,可以實現這組接口,以為特定的數據提供驅動。而數據庫的使用者,也可以通過這組接口方便地訪問數據庫,甚至在適當的時候,以非常小的代價遷移數據庫。

通常我們在以類似如下的方式導入數據庫驅動模塊時:

import   _ "github.com/Go-SQL-Driver/MySQL"

上面的 import 語句中的下劃線表示,我們要導入這個模塊,但不會直接使用其中的符號。但導入的時候,會執行模塊的初始化代碼,也就是其中定義的 init() 函數,在這個函數中數據庫驅動會自動將其自身注冊進 Go 的 database/sql 框架中,后面我們就可以方便地通過這個接口來訪問對應得數據了。

關于這組接口的詳細內容,可以參考 官方文檔

MySQL

目前網上流行的網站架構方式是 LAMP,其中的 M 即為 MySQL。作為數據庫,MySQL 以免費、開源、使用方便為優勢而成為了許多Web開發的后端數據庫存儲引擎。

MySQL 安裝

首先我們需要安裝 MySQL,這可以通過如下的命令來完成:

$ sudo apt install mysql-server
$ sudo apt-get install mysql-client
$ mysql_secure_installation

安裝之后,通過如下命令可以查看 MySQL 服務器占用的端口:

$ sudo lsof -i -P
COMMAND     PID        USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
. . . . . .
mysqld    17860       mysql   20u  IPv4 136588      0t0  TCP localhost:3306 (LISTEN)

可以看到 MySQL 服務器在 TCP 的 3306 端口監聽請求。

新MySQL建用戶

安裝好了 MySQL 之后,我們還需要創建用戶,以便于后面在代碼里使用。創建用戶的方法如下:

## 登錄MYSQL
$ mysql -u root -p
Enter password:
## 創建用戶
mysql> CREATE USER 'hanpfei'@'localhost' IDENTIFIED BY 'hanpfei';
## 刷新系統權限表
mysql>flush privileges;

這樣就創建了一個名為 hanpfei ,密碼為 hanpfei 的用戶。

然后登錄一下。

mysql> exit;
$ mysql -u hanpfei -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.7.17-0ubuntu0.16.04.1 (Ubuntu)
. . . . . .
mysql>

創建數據庫并為用戶授權

登錄MYSQL(有ROOT權限)。我里我以 ROOT 身份登錄.

$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.7.17-0ubuntu0.16.04.1 (Ubuntu)

為用戶創建一個數據庫 ( staff_info_db )

mysql>create database staff_info_db;

授權 hanpfei 用戶擁有 staff_info_db 數據庫的所有權限。

mysql>grant all privileges on staff_info_db.* to hanpfei@localhost identified by 'hanpfei';

刷新系統權限表

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

創建表

有了數據庫,接下來就是創建表了。建表語句如下:

CREATE TABLE `userinfo1` (
    `uid` INT(10) NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(64) NULL DEFAULT NULL,
    `departname` VARCHAR(64) NULL DEFAULT NULL,
    `created` DATE NULL DEFAULT NULL,
    PRIMARY KEY (`uid`)
);

CREATE TABLE `userdetail` (
    `uid` INT(10) NOT NULL DEFAULT '0',
    `intro` TEXT NULL,
    `profile` TEXT NULL,
    PRIMARY KEY (`uid`)
);

具體的建表可以通過如下得命令來完成:

$ mysql -u hanpfei -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 5.7.17-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use staff_info_db;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> CREATE TABLE `userinfo` (
    ->     `uid` INT(10) NOT NULL AUTO_INCREMENT,
    ->     `username` VARCHAR(64) NULL DEFAULT NULL,
    ->     `departname` VARCHAR(64) NULL DEFAULT NULL,
    ->     `created` DATE NULL DEFAULT NULL,
    ->     PRIMARY KEY (`uid`)
    -> );
Query OK, 0 rows affected (0.80 sec)

mysql> CREATE TABLE `userdetail` (
    ->     `uid` INT(10) NOT NULL DEFAULT '0',
    ->     `intro` TEXT NULL,
    ->     `profile` TEXT NULL,
    ->     PRIMARY KEY (`uid`)
    -> );
Query OK, 0 rows affected (0.80 sec)
mysql> exit
Bye

這樣我們需要的表就建好了。

用 Go 語言訪問 MySQL

安裝好了數據庫,并創建了適當的用戶、數據庫以及數據庫表之后,我們就可以開始用 Go 語言訪問 MySQL了。然而,在實際寫代碼之前,還要先下載對應的驅動。Go 語言中支持 MySQL 的驅動目前比較多,我們以支持 Go 語言標準 database/sql 接口的 github.com/Go-SQL-Driver/MySQL 為例來看。我們先要下載這個包:

$ go get github.com/Go-SQL-Driver/MySQL

然后來看如何使用 database/sql 接口對數據庫表進行增刪改查操作:

package main

import (
    _ "github.com/Go-SQL-Driver/MySQL"
    "fmt"
    "database/sql"
)

func checkErr(err error)  {
    if err != nil {
        panic(err)
    }
}

func mysqlTest()  {
    db, err := sql.Open("mysql", "hanpfei:hanpfei@/staff_info_db?charset=utf8")
    checkErr(err)
    defer db.Close()

    // Insert
    stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")
    checkErr(err)

    res, err := stmt.Exec("hanpfei", "R&D Department", "2016-05-23")
    checkErr(err)

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

    fmt.Println(id)

    // Update
    stmt, err = db.Prepare("UPDATE userinfo SET username=? where uid=?")
    checkErr(err)

    res, err = stmt.Exec("hanpfeiupdate", id)
    checkErr(err)

    affect, err := res.RowsAffected()
    checkErr(err)

    fmt.Println(affect)

    // Query
    rows, err := db.Query("SELECT * FROM userinfo")
    checkErr(err)

    for rows.Next() {
        var uid int
        var username string
        var department string
        var created string
        err = rows.Scan(&uid, &username, &department, & created)
        checkErr(err)
        fmt.Println(uid)
        fmt.Println(username)
        fmt.Println(department)
        fmt.Println(created)
    }

    // Delete data
    stmt, err = db.Prepare("DELETE from userinfo where uid=?")
    checkErr(err)

    res, err = stmt.Exec(id)
    checkErr(err)

    affect, err = res.RowsAffected()
    checkErr(err)

    fmt.Println(affect)

    checkErr(err)
}

func main()  {
    mysqlTest()
}

通過以上代碼,可以看出來 Go 語言操作 MySQL 數據庫還是非常方便的。關于這個數據庫驅動的用法更詳細的信息,可以參考其 官方文檔

SQLite3

SQLite 是一個開源的嵌入式系統的關系型數據庫,它是實現自包容、零配置且支持事務的 SQL 數據庫引擎。其特點是高度便攜、結構緊湊、高效且可靠。與其它許多數據庫相比,SQLite 的安裝運行都非常簡單。大多數情況下,只要確保 SQLite 的二進制文件存在,即可創建和訪問數據庫。

可以通過如下的命令來安裝 SQLite:

$ sudo apt-get install libsqlite3-0 libsqlite3-dev

SQLite 的命令行工具可裝可不裝,不影響我們通過代碼操作 SQLite 數據庫。

同樣我們需要選擇一款 SQLite 驅動。Go 語言支持 SQLite 的驅動也比較多,但好多都不支持 database/sql 接口。這里我們選擇支持 database/sql 接口的 github.com/mattn/go-sqlite3 。

在開始寫代碼前,要先安裝這個驅動:

$ go get github.com/mattn/go-sqlite3

建表的語句如下:

CREATE TABLE `userinfo` (
    `uid` INTEGER PRIMARY KEY AUTOINCREMENT,
    `username` VARCHAR(64) NULL,
    `departname` VARCHAR(64) NULL,
    `created` DATE NULL
);

CREATE TABLE `userdetail` (
    `uid` INT(10) NULL,
    `intro` TEXT NULL,
    `profile` TEXT NULL,
    PRIMARY KEY (`uid`)
);

不過我們同樣通過代碼來完成建表了。然后來看在 Go 語言中,具體如何操作 SQLite :

package main

import (
    _ "github.com/mattn/go-sqlite3"
    "database/sql"
    "fmt"
)

func checkErr(err error)  {
    if err != nil {
        panic(err)
    }
}

func testOperationForSqlite3(db *sql.DB)  {
    // Insert
    stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) values(?,?,?)")
    checkErr(err)

    res, err := stmt.Exec("hanpfei", "R&D Department", "2016-05-23")
    checkErr(err)

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

    fmt.Println(id)

    // Update
    stmt, err = db.Prepare("UPDATE userinfo SET username=? where uid=?")
    checkErr(err)

    res, err = stmt.Exec("hanpfeiupdate", id)
    checkErr(err)

    affect, err := res.RowsAffected()
    checkErr(err)

    fmt.Println(affect)

    // Query
    rows, err := db.Query("SELECT * FROM userinfo")
    checkErr(err)

    for rows.Next() {
        var uid int
        var username string
        var department string
        var created string
        err = rows.Scan(&uid, &username, &department, & created)
        checkErr(err)
        fmt.Println(uid)
        fmt.Println(username)
        fmt.Println(department)
        fmt.Println(created)
    }

    // Delete data
    stmt, err = db.Prepare("DELETE from userinfo where uid=?")
    checkErr(err)

    res, err = stmt.Exec(id)
    checkErr(err)

    affect, err = res.RowsAffected()
    checkErr(err)

    fmt.Println(affect)

    checkErr(err)
}

func createTableForSqlite3(db *sql.DB)  {
    createTableCommand := "CREATE TABLE userinfo (uid INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(64) NULL, " +
        "departname VARCHAR(64) NULL, created DATE NULL);"

    stmt, err := db.Prepare(createTableCommand)
    checkErr(err)

    _, err = stmt.Exec()
    checkErr(err)

    createTableCommand = "CREATE TABLE userdetail (uid INT(10) NULL, intro TEXT NULL, profile TEXT NULL, PRIMARY KEY (uid));"

    stmt, err = db.Prepare(createTableCommand)
    checkErr(err)

    _, err = stmt.Exec()
    checkErr(err)
}

func sqlite3Test()  {
    db, err := sql.Open("sqlite3", "./foo.db")
    checkErr(err)
    defer db.Close()

    createTableForSqlite3(db)
    testOperationForSqlite3(db)
}

func main()  {
    sqlite3Test()
}

執行上面的代碼,將看到如下的輸出:

/usr/lib/go/bin/go run /home/hanpfei0306/IdeaProjects/HelloGo/Sqlite3.go
1
1
1
hanpfeiupdate
R&D Department
2016-05-23T00:00:00Z
1

Process finished with exit code 0

我們可以看到,上面操作 SQLite 數據庫的代碼,和前面操作 MySQL 數據庫的代碼幾乎一模一樣。僅有的改變是導入的驅動變了,然后調用 sql,Open() 打開數據庫驅動的方式不同。

PostgreSQL

PostgreSQL 是一個開源的自由的對象-關系數據庫服務器,它以靈活的 BSD-Style 許可發行。相對于其它許多的開源數據庫系統(如 MySQL 和 Firebird)和商業數據庫系統(如 Oracle 和 MS SQL Server),它為我們提供了另外的一種選擇。

PostgreSQL 相對于 MySQL 而言更加龐大,因為它本是為替代 Oracle 而設計。

這里我們就來看一下如何用 Go 語言操作 PostgreSQL。

安裝

我們首先要安裝 PostgreSQL 服務器。使用如下命令,會自動安裝最新版,這里為 9.5 :

sudo apt-get install postgresql

安裝完成后,默認會:

(1)創建名為 “postgres” 的Linux用戶

(2)創建名為 “postgres”、不帶密碼的默認數據庫賬號作為數據庫管理員

(3)創建名為 “postgres” 的表

安裝完成后的一些默認信息如下:

config /etc/postgresql/9.5/main 
data /var/lib/postgresql/9.5/main
locale en_US.UTF-8 
socket /var/run/postgresql 
port 5432

通過 lsof -i 命令我們可以查看 PostgreSQL 服務器占用的端口,并確認其在正常運行:

$ sudo lsof -i -P
. . . . . .
postgres 24581   postgres    6u  IPv6284716     0t0  TCP localhost:5432 (LISTEN)
postgres 24581   postgres    7u  IPv4284717     0t0  TCP localhost:5432 (LISTEN)
postgres 24581   postgres   11u  IPv6279448     0t0  UDP localhost:42368->localhost:42368 
postgres 24583   postgres   11u  IPv6279448     0t0  UDP localhost:42368->localhost:42368 
postgres 24584   postgres   11u  IPv6279448     0t0  UDP localhost:42368->localhost:42368 
postgres 24585   postgres   11u  IPv6279448     0t0  UDP localhost:42368->localhost:42368 
postgres 24586   postgres   11u  IPv6279448     0t0  UDP localhost:42368->localhost:42368 
postgres 24587   postgres   11u  IPv6279448     0t0  UDP localhost:42368->localhost:42368

可以看到 PostgreSQL 服務器在 TCP 的 5432 端口上監聽請求,并開啟了多個進程來監聽。

配置

安裝完后會有 PostgreSQL 的客戶端 psql 可以用,通過 sudo -u postgres psql 進入,提示符變成 postgres=# :

$ sudo -u postgres psql
psql (9.5.6)
Type "help" for help.

postgres=#

在這里可以執行 SQL 語句和 psql 的基本命令。

新建 PostgreSQL用戶

我們可以通過如下的命令

postgres=# CREATE USER hanpfei PASSWORD 'hanpfei' CREATEDB;
CREATE ROLE

通過 \du 可以查看當前已經存在的用戶列表:

postgres=# \du
 List of roles
 Role name | Attributes | Member of 
-----------+------------------------------------------------------------+-----------
 hanpfei | Create DB | {}
 postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

此時我們以新創建的用戶登錄PostgreSQL,會報出如下得error:

$ sudo -u postgres psql -U hanpfei
psql: FATAL:  Peer authentication failed for user "hanpfei"

我們可以通過修改 pg_hba.conf 文件來解決這個問題:

$ sudo gedit /etc/postgresql/9.5/main/pg_hba.conf

將其中 除 postgres 用戶外 的所有用戶的 METHOD 都從 peer 或 ident 改為 md5 或 trust 。

修改完畢,保存退出。

然后執行如下命令重新加載配置:

$ /etc/init.d/postgresql reload

再次嘗試用新創建的用戶的登錄 PostgreSQL 時報出了新的 error:

$ sudo -u postgres psql -U hanpfei
Password for user hanpfei: 
psql: FATAL:  database "hanpfei" does not exist

提示用戶的數據庫不存在。我們還需要再次登錄 postgres 用戶,為我們的新用戶創建數據庫:

$ sudo -u postgres psql
psql (9.5.6)
Type "help" for help.

postgres=# create database hanpfei;
CREATE DATABASE
postgres=# \q

然后就可以以新用戶登錄了:

$ sudo -u postgres psql -U hanpfei
[sudo] hanpfei0306 的密碼: 
Password for user hanpfei: 
psql (9.5.6)
Type "help" for help.

hanpfei=>

這里我們需要輸入兩次密碼,一次是當前 Linux 用戶的用戶密碼,用來執行 sudo,另一次是數據庫的用戶的密碼,用來登錄數據庫。

接著我們創建一個新的應用數據庫,并選擇它作為我們當前使用的數據庫,這可以通過 \c 命令來實現:

hanpfei=> \l
                                    List of databases
     Name      |Owner|Encoding|Collate|Ctype|Access privileges
---------------+----------+----------+-------------+-------------+-----------------------
 hanpfei       |postgres|UTF8|zh_CN.UTF-8|zh_CN.UTF-8|
 postgres      |postgres|UTF8|zh_CN.UTF-8|zh_CN.UTF-8|
 staff_info_db |hanpfei|UTF8|zh_CN.UTF-8|zh_CN.UTF-8|
 template0     |postgres|UTF8|zh_CN.UTF-8|zh_CN.UTF-8|=c/postgres +
               |||||postgres=CTc/postgres
 template1     |postgres|UTF8|zh_CN.UTF-8|zh_CN.UTF-8|=c/postgres +
               |||||postgres=CTc/postgres
(5 rows)

hanpfei=> create database staff_info_db;

hanpfei=> \c staff_info_db;
You are now connected to database "staff_info_db" as user "hanpfei".

staff_info_db=>

上面的 \l 是用來列出當前已創建的所有數據庫的。注意我們切換了數據庫之后,命令輸入提示字符串也變為了新數據庫的名字。

然后創建表。建表語句如下:

CREATE TABLE userinfo (
    uid serial NOT NULL,
    username character varying(100) NOT NULL,
    departname character varying(100) NOT NULL,
    created date,
    CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
)
WITH (OIDS=FALSE);

CREATE TABLE userdetail (
    uid integer,
    intro character varying(100),
    profile character varying(100)
)
WITH (OIDS=FALSE);

具體命令則是:

staff_info_db=> CREATE TABLE userinfo (
staff_info_db(>     uid serial NOT NULL,
staff_info_db(>     username character varying(100) NOT NULL,
staff_info_db(>     departname character varying(100) NOT NULL,
staff_info_db(>     created date,
staff_info_db(>     CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
staff_info_db(> )
staff_info_db-> WITH (OIDS=FALSE);
CREATE TABLE
staff_info_db=> CREATE TABLE userdetail (
staff_info_db(>     uid integer,
staff_info_db(>     intro character varying(100),
staff_info_db(>     profile character varying(100)
staff_info_db(> )
staff_info_db-> WITH (OIDS=FALSE);
CREATE TABLE
staff_info_db=>

權限

創建的表還可以賦予其它用戶完全的權限,比如,以 postgres 用戶創建的表的完全的權限賦予新用戶:

postgres=# GRANT ALL ON userinfo TO hanpfei;
postgres=# GRANT ALL ON userinfo TO userdetail;

使用 Go 語言操作 PostgreSQL

同樣我們需要先找個驅動。Go 語言的 PostgreSQL 驅動也很多。這里我們選用支持 database/sql 接口的驅動 github.com/lib/pq ,這個項目由 github.com/bmizerany/pq 遷移而來,而后者目前已經廢棄。我們還是要先安裝:

$ go get github.com/lib/pq

然后用 Go 語言訪問 PostgreSQL:

package main

import (
    _ "github.com/lib/pq"
    "fmt"
    "database/sql"
)

func checkErr(err error)  {
    if err != nil {
        panic(err)
    }
}

func testOperationForPostgreSQL(db *sql.DB)  {
    // Insert
    stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) RETURNING uid")
    checkErr(err)

    res, err := stmt.Exec("hanpfei", "R_D_Department", "2016-05-23")
    checkErr(err)

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

    fmt.Println(res)

    // Update
    stmt, err = db.Prepare("UPDATE userinfo SET username=$1 where uid=$2")
    checkErr(err)

    res, err = stmt.Exec("hanpfeiupdate", 1)
    checkErr(err)

    affect, err := res.RowsAffected()
    checkErr(err)

    fmt.Println(affect)

    // Query
    rows, err := db.Query("SELECT * FROM userinfo")
    checkErr(err)

    for rows.Next() {
        var uid int
        var username string
        var department string
        var created string
        err = rows.Scan(&uid, &username, &department, & created)
        checkErr(err)
        fmt.Println(uid)
        fmt.Println(username)
        fmt.Println(department)
        fmt.Println(created)
    }

    // Delete data
    stmt, err = db.Prepare("DELETE from userinfo where uid=$1")
    checkErr(err)

    res, err = stmt.Exec(1)
    checkErr(err)

    affect, err = res.RowsAffected()
    checkErr(err)

    fmt.Println(affect)

    checkErr(err)
}

func postgreSqlTest()  {
    db, err := sql.Open("postgres", "user=hanpfei password=hanpfei dbname=staff_info_db sslmode=disable")
    checkErr(err)
    defer db.Close()

    testOperationForPostgreSQL(db)
}

func main()  {
    postgreSqlTest()
}

從上面的代碼中可以看到,PostgreSQL 是通過 “$1,$2”這種方式來占位要傳入的參數的,而不是 MySQL 中的 “?” 另外在 sql.Open() 中的 dsn 信息的格式也與 MySQL 不同,因而在使用時需要注意。

此外, PostgreSQL 不支持 LastInsertId() 函數,因為它內部沒有實現類似 MySQL 的自增 ID 返回。其它的代碼則幾乎一模一樣。

NoSQL 數據庫

NoSQL (Not only SQL),指的是非關系型數據庫。隨著 Web 2.0 的興起,傳統的關系型數據庫在應付新應用,特別是超大規模和高并發得 SNS 型 Web 2.0 純動態網站時已經顯得力不從心,暴露了很多難以客服得問題,而非關系型數據庫則由于其自身的有點,而得到迅速得發展。

在看了上面的幾種 SQL 數據庫之后,接下來我們將學習用 Go 語言操作幾種 NoSQL 數據庫,主要是 Redis 和 MongoDB。

Redis

Redis 是一個開源的(BSD 許可),基于內存的數據結構存儲產品,它可以被用作數據庫,緩存和消息代理。它支持的數據結構非常多,如 string(字符串),hash(哈希),list(列表),set(集合),帶有范圍查詢的sorted set(有序集合),bitmap(位圖),超文本和具有半徑查詢的地理空間索引。Redis具有內置復制,Lua腳本,LRU驅逐,事務和不同級別的磁盤持久性,并通過Redis Sentinel提供高可用性,并通過Redis Cluster進行自動分區。

Redis 是一個超高性能的 key-value 數據庫。Redis 的出現,很大程度補償了memcached 這類 key-value 存儲的不足,在部 分場合可以對關系數據庫起到很好的補充作用。它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。

這里我們就來看一下如何用 Go 語言操作Redis。

Redis 安裝

使用如下命令,會自動安裝最新版

$ sudo apt-get install redis-server redis-tools

通過 lsof -i 命令我們可以查看 Redis 服務器占用的端口。

$ sudo lsof -i -P
COMMAND     PID        USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
. . . . . .
redis-ser  2977       redis    4u  IPv4 507101      0t0  TCP localhost:6379 (LISTEN)

可以看到 Redis 服務器在 TCP 的 6379 端口監聽請求。

Redis 還提供了功能強大的命令行工具

$ redis-cli
127.0.0.1:6379> help
redis-cli 3.0.6
Type: "help @<group>" to get a list of commands in <group>
      "help <command>" for help on <command>
      "help <tab>" to get a list of possible help topics
      "quit" to exit

Go 程序訪問 Redis

Go 語言的 Redis 客戶端驅動還是很多的,具體可以通過 Redis 的 Client 頁 找到它們。當前還處于比較活躍的狀態,也就是近 6 個月官方 repo 有過更新的驅動如下:

https://github.com/go-redis/redis
https://github.com/keimoon/gore
https://github.com/gosexy/redis
https://github.com/tideland/golib
https://github.com/garyburd/redigo
https://github.com/mediocregopher/radix.v2

其中最后兩個,是目前 Redis 官方推薦使用的 Go 驅動。這里我們以最后一個為例,來看要如何在 Go 代碼里操作 Redis。然而,在開始之前,我們還是要先安裝相應的包:

$ go get github.com/mediocregopher/radix.v2/redis

接著來看具體如何通過 Go 語言訪問 Redis:

package main

import (
    "fmt"
    "github.com/mediocregopher/radix.v2/redis"
)

func checkErr(err error)  {
    if err != nil {
        panic(err)
    }
}

func testRedisWithRadix()  {
    client, err := redis.Dial("tcp", "localhost:6379")
    checkErr(err)

    err = client.Cmd("SET", "a", "hello").Err
    checkErr(err)

    val, err := client.Cmd("GET", "a").Str()
    checkErr(err)

    fmt.Println("Redis val:")
    fmt.Println(string(val))

    err = client.Cmd("DEL", "a").Err
    checkErr(err)

    // list operation
    vals := []string{"a", "b", "c", "d", "e"}
    for _, v := range vals {
        err = client.Cmd("RPUSH", "l", v).Err
        checkErr(err)
    }
    dbvals, err := client.Cmd("LRANGE", "l", 0, 4).List()
    checkErr(err)
    for i, v := range dbvals  {
        fmt.Println(i, ":", string(v))
    }
    err = client.Cmd("DEL", "l").Err
    checkErr(err)
}

func main()  {
    testRedisWithRadix()
}

運行上面代碼,可以看到如下的輸出:

$ /usr/lib/go/bin/go run /home/hanpfei0306/IdeaProjects/HelloGo/Redis.go
Redis val:
hello
0 : a
1 : b
2 : c
3 : d
4 : e

Process finished with exit code 0

我們可以看到,操作 Redis 非常方便,大多只要用 client 命令即可。關于 Radix 用法的更多詳細內容,可以參考其 官方文檔

MongoDB

MongoDB 是一個高性能功能強大而流行的分布式文檔存儲 NoSQL (Not Only SQL) 數據庫產品。它是一個介于關系數據庫和非關系數據庫之間的產品,是非關系數據庫當中功能最豐富,最像關系數據庫的。他支持的數據結構非常松散,是類似json的bjson格式,因此可以存儲比較復雜的數據類型。Mongo最大的特點是他支持的查詢語言非常強大,其語法有點類似于面向對象的查詢語言,幾乎可以實現類似關系數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。

下面我們來看一下如何通過 Go 語言操作 MongoDB。

MongoDB 安裝

首先需要安裝 MongoDB。使用如下命令,會自動安裝最新版 MongoDB,這里是 2.6.10 版。

$ sudo apt-get install mongodb mongodb-clients mongodb-server

通過 lsof -i 命令我們可以查看 MongoDB 服務器占用的端口,并確認 MongoDB 服務器的正常運行。

 sudo lsof -i -P
COMMAND     PID        USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
. . . . . .
mongod     7838     mongodb    8u  IPv4 536811      0t0  TCP localhost:27017 (LISTEN)

可以看到 MongoDB 服務器在 TCP 的 27017 端口監聽請求。

創建數據庫

安裝了 MongoDB 服務器之后,我們還要創建數據庫,以備后面在代碼里面用。我們可以通過 MongoDB 的 shell 版本,使用 use 命令創建數據庫:

$ mongo
MongoDB shell version: 2.6.10
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
    http://docs.mongodb.org/
Questions? Try the support group
    http://groups.google.com/group/mongodb-user
> use people_info
switched to db people_info

use 命令在 MySQL 中用于選擇已經創建好的數據庫,而在 MongoDB 中則會自動創建當前還不存在的數據庫。

Go 程序訪問 MongoDB

在開始編寫 Go 代碼訪問 MongoDB 數據庫之前,我們還要先下載 MongoDB 的Go語言驅動。在 MongoDB 的 官方 Drivers主頁 可以找到可用的 Go 語言驅動。當前官方推薦的只有開源社區支持的 mgo 驅動。 mgo 主頁 。mgo 的 GitHub 主頁 。通過 go get 命令安裝我們需要的兩個 mgo Go 包:

$ go get gopkg.in/mgo.v2
$ go get gopkg.in/mgo.v2/bson

接著來看具體如何通過 Go 語言操作 MongoDB。

package main

import (
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "fmt"
)

type Person struct {
    Name string
    Phone string
}

funccheckErr(err error)  {
    if err != nil {
        panic(err)
    }
}

functestMongoDB()  {
    session, err := mgo.Dial("localhost")
    checkErr(err)
    defer session.Close()

    session.SetMode(mgo.Monotonic, true)
    c := session.DB("people_info").C("people")

    err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
        &Person{"Cla", "+55 53 8402 8510"})
    checkErr(err)

    result := Person{}
    err = c.Find(bson.M{"name": "Ale"}).One(&result)
    checkErr(err)

    fmt.Println("Phone:", result.Phone)
}

funcmain()  {
    testMongoDB()
}

操作與許多 SQL數據庫的 ORM 庫提供的很相似,可以直接操作對象。

 

來自:https://www.wolfcstech.com/2017/02/26/一文學會Go語言數據庫操作/

 

 本文由用戶 sicoly 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!