在Go中使用SQL數據庫

在本文中,我列出瞭如何使用Go執行常見的SQL數據庫操作。

簡介database/sql

Go在其標準庫中提供了乾淨的SQL數據庫APIdatabase/sql軟件包,但必須單獨安裝特定的數據庫驅動程序。

這是一種明智的方法,因為它提供了幾乎每個數據庫驅動程序都實現的通用接口。

如果要使用MySQL,可以使用https://github.com/go-sql-driver/mysql

如果您使用的是PostgreSQL,請使用https://github.com/lib/pq

您只需要使用以下內容包含libimport _database/sqlAPI將配置為啟用該驅動程序:

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

打開數據庫連接

儘管目標是使其抽象化,但在某些方面仍然存在差異,例如在連接數據庫的方式上:

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

//… db, err := sql.Open(“mysql”, “theUser:[email protected]/theDbName”) if err != nil { panic(err) }

import “database/sql”
import _ github.com/lib/pq

//… db, err := sql.Open(“postgres”, “user=theUser dbname=theDbName sslmode=verify-full”) if err != nil { panic(err) }

但是實際的大多數API都是與數據庫無關的,並且可以很容易地互換(這裡不談論SQL,僅指數據庫API)。

關閉數據庫連接

在有意義的地方,您應該始終關閉數據庫連接。

您可以照常使用defer在打開數據庫連接的函數結束時將其關閉:

db, err := sql.Open("postgres", psqlInfo)
defer db.Close()

從數據庫中提取數據

選擇單行

查詢表分兩個步驟。首先你打電話db.QueryRow(),然後您致電Scan()結果。

例子:

id := 1
var col string
sqlStatement := `SELECT col FROM my_table WHERE id=$1`
row := db.QueryRow(sqlStatement, id)
err := row.Scan(&col)
if err != nil {
    if err == sql.ErrNoRows {
        fmt.Println("Zero rows found")
    } else {
        panic(err)
    }
}

db.QueryRow()用於查詢表中的單個值。

簽名:

func (db *DB) QueryRow(query string, args ...interface{}) *Row

它返回一個指向db.Row價值。

(*Row) Scan掃描行,將列值複製到傳遞給它的參數中。

簽名:

func (r *Row) Scan(dest ...interface{}) error

如果返回了多個行,則僅掃描第一行並忽略其餘部分。

如果未返回任何行,則返回一個ErrNoRows錯誤

var ErrNoRows = errors.New("sql: no rows in result set")

選擇多行

為了查詢單行,我們使用了db.QueryRow()。要查詢多行,我們使用db.Query(),它返回一個*Rows價值。

從文檔中:

//Rows is the result of a query. Its cursor starts before  the first row of the result set. Use Next to advance through the rows:

    rows, err := db.Query("SELECT ...")
    ...
    defer rows.Close()
    for rows.Next() {
        var id int
        var name string
        err = rows.Scan(&id, &name)
        ...
    }
     err = rows.Err() // get any error encountered ing iteration
    ...

// Err返回在迭代過程中遇到的錯誤(如果有)。 //可以在顯式或隱式的Close之後調用Err。

我們需要迭代rows.Next(),這使我們可以致電rows.Scan()進入循環。

如果在準備下一行時發生任何錯誤,則循環結束,我們可以通過調用來獲取錯誤rows.Err()

type Timeline struct {
    Id int
    Content string
}
rows, err := db.Query(`SELECT id, content FROM timeline`)
if err != nil {
    panic(err)
}
defer rows.Close()
for rows.Next() {
    timeline := Timeline{}
    err = rows.Scan(&timeline.Id, &timeline.Content)
    if err != nil {
        panic(err)
    }
    fmt.Println(timeline)
}
err = rows.Err()
if err != nil {
    panic(err)
}

更多教程: