開啟資料庫控制代碼

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 method 構建連線字串。

// Specify connection properties.
cfg := mysql.NewConfig()
cfg.User = username
cfg.Passwd = password
cfg.Net = "tcp"
cfg.Addr = "127.0.0.1:3306"
cfg.DBName = "jazzrecords"

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

使用 Connector 開啟

當您想利用連線字串中不可用的驅動程式特定連線特性時,請使用 sql.OpenDB function。每個驅動程式都支援自己的連線屬性集,通常提供自定義針對特定 DBMS 的連線請求的方式。

將前面的 sql.Open 示例改為使用 sql.OpenDB,您可以使用以下程式碼建立控制代碼

// Specify connection properties.
cfg := mysql.NewConfig()
cfg.User = username
cfg.Passwd = password
cfg.Net = "tcp"
cfg.Addr = "127.0.0.1:3306"
cfg.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,您的程式碼可以使用該 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.