網站首頁 編程語言 正文
前言:
本篇文章對如何使用golang連接并操作postgre數據庫進行了簡要說明。文中使用到的主要工具:DBeaver21、VSCode,Golang1.17。
以用戶,文章,評論三個表作為例子,下面是數據庫建表sql:
CREATE TABLE public.user_info ( u_id serial4 NOT NULL, user_name varchar NULL, create_time date NULL, CONSTRAINT user_info_pk PRIMARY KEY (u_id) ); CREATE TABLE public.user_info ( u_id serial4 NOT NULL, user_name varchar NULL, create_time date NULL, CONSTRAINT user_info_pk PRIMARY KEY (u_id) ); CREATE TABLE public."comment" ( c_id serial4 NOT NULL, "content" varchar NULL, CONSTRAINT comment_pk PRIMARY KEY (c_id) );
連接數據庫
連接postgre數據庫的驅動有很多,我們選用了github.com/lib/pq
。下面看連接的方法。我們引入pq
包時使用了_
進行匿名加載,而不是直接使用驅動包。在對數據庫的操作仍然是使用自帶的sql
包。另外,postgre默認使用的是public
模式(schema),我們創建的表也是在這個模式下的??梢灾苯釉跀祿熘行薷哪J模式或者在連接url中添加currentSchema=myschema
來指定默認的模式,當然也可以在sql中使用myschema.TABLE
來指定要訪問的模式。
package main import ( "database/sql" "fmt" _ "github.com/lib/pq" ) var db *sql.DB func DbOpen() { var err error //參數根據自己的數據庫進行修改 db, err = sql.Open("postgres", "host=localhost port=5432 user=angelhand password=2222 dbname=ahdb sslmode=disable") checkError(err) err = db.Ping() checkError(err) }
sql.DB
需要注意的是,sql.DB
并不是數據庫連接,而是一個go中的一個數據結構:
type DB struct { // Atomic access only. At top of struct to prevent mis-alignment // on 32-bit platforms. Of type time.Duration. waitDuration int64 // Total time waited for new connections. connector driver.Connector // numClosed is an atomic counter which represents a total number of // closed connections. Stmt.openStmt checks it before cleaning closed // connections in Stmt.css. numClosed uint64 mu sync.Mutex // protects following fields freeConn []*driverConn connRequests map[uint64]chan connRequest nextRequest uint64 // Next key to use in connRequests. numOpen int // number of opened and pending open connections // Used to signal the need for new connections // a goroutine running connectionOpener() reads on this chan and // maybeOpenNewConnections sends on the chan (one send per needed connection) // It is closed during db.Close(). The close tells the connectionOpener // goroutine to exit. openerCh chan struct{} closed bool dep map[finalCloser]depSet lastPut map[*driverConn]string // stacktrace of last conn's put; debug only maxIdleCount int // zero means defaultMaxIdleConns; negative means 0 maxOpen int // <= 0 means unlimited maxLifetime time.Duration // maximum amount of time a connection may be reused maxIdleTime time.Duration // maximum amount of time a connection may be idle before being closed cleanerCh chan struct{} waitCount int64 // Total number of connections waited for. maxIdleClosed int64 // Total number of connections closed due to idle count. maxIdleTimeClosed int64 // Total number of connections closed due to idle time. maxLifetimeClosed int64 // Total number of connections closed due to max connection lifetime limit. stop func() // stop cancels the connection opener. }
在拿到sql.DB
時并不會創建新的連接,而可以認為是拿到了一個數據庫連接池,只有在執行數據庫操作(如Ping()操作)時才會自動生成一個連接并連接數據庫。在連接操作執行完畢后應該及時地釋放。此處說的釋放是指釋放連接而不是sql.DB
連接,通常來說一個sql.DB
應該像全局變量一樣長期保存,而不要在某一個小函數中都進行Open()
和Close()
操作,否則會引起資源耗盡的問題。
增刪改查
下面代碼實現對數據簡單的增刪改查操作。
插入數據
func insert() { stmt, err := db.Prepare("INSERT INTO user_info(user_name,create_time) VALUES($1,$2)") if err != nil { panic(err) } res, err := stmt.Exec("ah", time.Now()) if err != nil { panic(err) } fmt.Printf("res = %d", res) }
使用Exec()
函數后會返回一個sql.Result
即上面的res
變量接收到的返回值,它提供了LastInserId() (int64, error)
和RowsAffected() (int64, error)
分別獲取執行語句返回的對應的id和語句執行所影響的行數。
更新數據
func update() { stmt, err := db.Prepare("update user_info set user_name=$1 WHERE u_id=$2") if err != nil { panic(err) } res, err := stmt.Exec("angelhand", 1) if err != nil { panic(err) } fmt.Printf("res = %d", res) }
查詢數據
結構體如下:
type u struct { id int user_name string create_time time.Time }
接下來是查詢的代碼
func query() { rows, err := db.Query("select u_id, user_name, create_time from user_info where user_name=$1", "ah") if err != nil { panic(err) } //延遲關閉rows defer rows.Close() for rows.Next() { user := u{} err := rows.Scan(&user.id, &user.user_name, &user.create_time) if err != nil { panic(err) } fmt.Printf("id = %v, name = %v, time = %v\n", user.id, user.user_name, user.create_time) } }
可以看到使用到的幾個關鍵函數rows.Close()
,rows.Next()
,rows.Scan()
。其中rows.Next()
用來遍歷從數據庫中獲取到的結果集,隨用用rows.Scan()
來將每一列結果賦給我們的結構體。
需要強調的是rows.Close()
。每一個打開的rows
都會占用系統資源,如果不能及時的釋放那么會耗盡系統資源。defer
語句類似于java中的finally
,功能就是在函數結束前執行后邊的語句。換句話說,在函數結束前不會執行后邊的語句,因此在耗時長的函數中不建議使用這種方式釋放rows
連接。如果要在循環中重發查詢和使用結果集,那么應該在處理完結果后顯式調用rows.Close()
。
db.Query()
實際上等于創建db.Prepare()
,執行并關閉之三步操作。
還可以這樣來查詢單條記錄:
err := db.Query("select u_id, user_name, create_time from user_info where user_name=$1", "ah").Scan(&user.user_name)
刪除數據
func delete() { stmt, err := db.Prepare("delete from user_info where user_name=$1") if err != nil { panic(err) } res, err := stmt.Exec("angelhand") if err != nil { panic(err) } fmt.Printf("res = %d", res) }
總結
原文鏈接:https://blog.csdn.net/qq_42893430/article/details/122072831
相關推薦
- 2022-10-27 Python使用pandas將表格數據進行處理_python
- 2022-12-09 Python?hashlib模塊詳細講解使用方法_python
- 2022-10-23 C++繼承與菱形繼承詳細介紹_C 語言
- 2022-07-04 python生成單位陣或對角陣的三種方式小結_python
- 2021-11-30 Linux?Autofs自動掛載服務安裝部署教程_Linux
- 2022-09-08 Python數據分析基礎之異常值檢測和處理方式_python
- 2022-06-21 C#實現XML文件與DataTable、Dataset互轉_C#教程
- 2022-08-18 python打印日志方法的使用教程(logging模塊)_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支