開啟資料庫控制代碼

透過降低您管理連線的需求,database/sql 套件簡化了資料庫存取。與許多資料存取 API 不同,使用 database/sql 時,您不會明確開啟連線、執行工作,然後關閉連線。相反地,您的程式碼會開啟一個代表連線池的資料庫控制代碼,然後使用控制代碼執行資料存取作業,僅在需要釋放資源(例如已擷取列或已準備好的陳述式所持有的資源)時,才會呼叫 Close 方法。

換句話說,它是資料庫控制代碼,由 sql.DB 表示,它會處理連線,並代表您的程式碼開啟和關閉它們。由於您的程式碼使用控制代碼執行資料庫作業,因此這些作業可以同時存取資料庫。如需詳細資訊,請參閱 管理連線

注意:您也可以保留資料庫連線。如需詳細資訊,請參閱 使用專用連線

除了 database/sql 套件中提供的 API 之外,Go 社群已開發出適用於所有最常見(以及許多不常見)資料庫管理系統 (DBMS) 的驅動程式。

在開啟資料庫控制代碼時,請遵循下列高階步驟

  1. 尋找驅動程式。

    驅動程式會在您的 Go 程式碼和資料庫之間轉譯要求和回應。如需詳細資訊,請參閱 尋找和匯入資料庫驅動程式

  2. 開啟資料庫控制代碼。

    匯入驅動程式後,您可以開啟特定資料庫的控制代碼。如需詳細資訊,請參閱 開啟資料庫控制代碼

  3. 確認連線。

    開啟資料庫控制代碼後,您的程式碼可以檢查是否有可用的連線。如需詳細資訊,請參閱 確認連線

您的程式碼通常不會明確開啟或關閉資料庫連線,這是由資料庫控制代碼執行的。但是,您的程式碼應該釋放它沿途取得的資源,例如包含查詢結果的 sql.Rows。如需詳細資訊,請參閱 釋放資源

尋找和匯入資料庫驅動程式

您需要支援您正在使用的 DBMS 的資料庫驅動程式。如需尋找資料庫驅動程式的資訊,請參閱 SQLDrivers

若要讓您的程式碼可以使用驅動程式,請將它匯入,就像匯入其他 Go 套件一樣。以下是一個範例

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

請注意,如果你未直接從驅動程式套件呼叫任何函式,例如當它被 sql 套件隱含使用時,你需要使用空白匯入,它會在匯入路徑前加上底線

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

注意:建議避免將資料庫驅動程式的 API 用於資料庫操作。請改用 database/sql 套件中的函式。這有助於讓你的程式碼與 DBMS 鬆散耦合,讓你在需要時更容易切換到不同的 DBMS。

開啟資料庫控制代碼

sql.DB 資料庫控制代碼提供從資料庫讀取和寫入資料庫的能力,可以個別或在交易中進行。

你可以透過呼叫 sql.Open(它會取得連線字串)或 sql.OpenDB(它會取得 driver.Connector)來取得資料庫控制代碼。兩者都會傳回一個指向 sql.DB 的指標。

注意:請務必將你的資料庫憑證排除在 Go 來源之外。更多資訊,請參閱 儲存資料庫憑證

使用連線字串開啟

當你想要使用連線字串連線時,請使用 sql.Open 函式。字串的格式會根據你使用的驅動程式而有所不同。

以下是一個 MySQL 的範例

db, err = sql.Open("mysql", "username:password@tcp(127.0.0.1:3306)/jazzrecords")
if err != nil {
    log.Fatal(err)
}

不過,你可能會發現以更結構化的方式擷取連線屬性會讓你的程式碼更具可讀性。詳細資訊會因驅動程式而異。

例如,您可以用以下內容取代前一個範例,它使用 MySQL 驅動程式的 Config 來指定屬性,並使用其 FormatDSN 方法 來建立連線字串。

// Specify connection properties.
cfg := mysql.Config{
    User:   username,
    Passwd: password,
    Net:    "tcp",
    Addr:   "127.0.0.1:3306",
    DBName: "jazzrecords",
}

// Get a database handle.
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
    log.Fatal(err)
}

使用連接器開啟

當您想要利用連線字串中沒有提供的特定於驅動程式的連線功能時,請使用 sql.OpenDB 函數。每個驅動程式都支援其自己的連線屬性組,通常提供自訂連線要求的方式,特定於 DBMS。

調整前一個 sql.Open 範例以使用 sql.OpenDB,您可以使用類似以下的程式碼建立一個控制代碼

// Specify connection properties.
cfg := mysql.Config{
    User:   username,
    Passwd: password,
    Net:    "tcp",
    Addr:   "127.0.0.1:3306",
    DBName: "jazzrecords",
}

// Get a driver-specific connector.
connector, err := mysql.NewConnector(&cfg)
if err != nil {
    log.Fatal(err)
}

// Get a database handle.
db = sql.OpenDB(connector)

處理錯誤

您的程式碼應檢查嘗試建立控制代碼的錯誤,例如使用 sql.Open。這不會是連線錯誤。相反地,如果 sql.Open 無法初始化控制代碼,您將會收到錯誤。例如,如果它無法解析您指定的 DSN,就會發生這種情況。

確認連線

當您開啟資料庫控制代碼時,sql 套件可能不會立即建立新的資料庫連線。相反地,它可能會在您的程式碼需要時建立連線。如果您不會立即使用資料庫,而且想要確認可以建立連線,請呼叫 PingPingContext

以下範例中的程式碼會對資料庫執行 ping 以確認連線。

db, err = sql.Open("mysql", connString)

// Confirm a successful connection.
if err := db.Ping(); err != nil {
    log.Fatal(err)
}

儲存資料庫憑證

避免在 Go 原始碼中儲存資料庫憑證,這可能會讓其他人看到您的資料庫內容。相反地,請找出一個方法將它們儲存在程式碼外部但程式碼可用的位置。例如,考慮一個儲存憑證並提供 API 供您的程式碼用於驗證 DBMS 的秘密保管應用程式。

一種常見的做法是在程式啟動前將機密儲存在環境中,可能從機密管理員載入,然後您的 Go 程式可以使用 os.Getenv 讀取它們

username := os.Getenv("DB_USER")
password := os.Getenv("DB_PASS")

這種做法也讓您可以在本地測試時自行設定環境變數。

釋放資源

儘管您不會使用 database/sql 套件明確管理或關閉連線,但您的程式碼應該在不再需要時釋放取得的資源。這些資源可能包括由表示查詢回傳資料的 sql.Rows 或表示已準備好陳述式的 sql.Stmt 所持有的資源。

通常,您可以透過遞延呼叫 Close 函式來關閉資源,以便在封閉函式結束前釋放資源。

以下範例中的程式碼遞延 Close 以釋放由 sql.Rows 所持有的資源。

rows, err := db.Query("SELECT * FROM album WHERE artist = ?", artist)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

// Loop through returned rows.