久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

如何理解Golang牽手PostgreSQL增刪改查+不寫結構快速掃描字段

145次閱讀
沒有評論

共計 7358 個字符,預計需要花費 19 分鐘才能閱讀完成。

行業資訊    
數據庫    
如何理解 Golang 牽手 PostgreSQL 增刪改查 + 不寫結構快速掃描字段

本篇內容介紹了“如何理解 Golang 牽手 PostgreSQL 增刪改查 + 不寫結構快速掃描字段”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

驅動安裝

執行以下命令安裝 postgresql 驅動

go get github.com/lib/pq

pq 包支持的功能

SSL

作為驅動程序, 與 database/sql 結合處理連接相關操作

掃描時間 time.Time 類型, 如 timestamp[tz], time[tz], date

掃描二進制 blobs 對象 (Blob 是內存中的數據緩沖, 用來匹配 strign 類型的 ID 和字節切片), 如: bytea

PostgreSQL 的 hstore 數據類型支持

支持 COPY FROM

pq.ParseURL 方法用來將 urls 轉化為 sql.Open 的連接字符串

支持許多 libpq 庫兼容的環境變量

支持 Unix socket

支持通知 Notifications, 如:LISTEN/NOTIFY

支持 pgpass

GSS (Kerberos) 認證

連接字符串參數

pq 包與 libpq 類似 (libpq 是用 C 編寫的底層接口,   為其他高級語言比如 C ++,Perl,Python,Tcl 和 ECPG 等提供底層 PostgreSQL 支持). 建立連接時需要提供連接參數,   一部分支持 libpq 的參數也支持 pq, 額外的, pq 允許在連接字符串中指定運行時參數 (如:search_path 或 work_mem),  libpq 則不能在連接字符串中指定運行時參數, 只能在 option 參數中指定.

pq 包為了兼容 libpq 包, 下面的連接參數都支持

* dbname -  需要連接的數據庫名  * user -  需要使用的用戶名  * password -  該用戶的密碼  * host -  需要連接的 postgresql 主機, unix 域名套接字以 / 開始,  默認是 localhost * port - postgresql 綁定的端口  (默認 5432) * sslmode -  是否使用 SSL (默認是啟用 (require), libpq 包默認不啟用 SSL) * fallback_application_name -  失敗時, 可以提供一個應用程序名來跟蹤. * connect_timeout -  連接最大等待秒數, 0 或者不指定,  表示不確定時間的等待  * sslcert -  證書文件位置,  文件中必須包含 PEM 編碼的數據  * sslkey -  密鑰文件位置,  文件中必須包含 PEM 編碼的數據  * sslrootcert -  根證書文件位置,  文件中必須包含 PEM 編碼的數據 

sslmode 支持一下模式

* disable -  禁用 SSL * require -  總是使用 SSL(跳過驗證) * verify-ca -  總是使用 SSL (驗證服務器提供的證書是由可信的 CA 簽署的) * verify-full -  總是使用 SSL(驗證服務器提供的證書是由受信任的 CA 簽署的,并驗證服務器主機名是否與證書中的主機名匹配)

更多連接字符串參數請參考官方文檔

對包含空格的參數, 需要使用單引號, 如:

user=pqgotest password= with spaces

使用反斜杠進行轉義, 如:

user=space\ man password= it\ s valid

注意: 如果要設置 client_encoding 連接參數 (用于設置連接的編碼), 必須設置為 UTF8 , 才能與 Postgres 匹配,   設置為其他值將會報錯.

除了上面的參數, 在連接字符串中也可以通過后臺設置運行時參數, 詳細運行時參數, 請參考 runtime-config

支持 libpq 的大部分環境變量也支持 pq 包, 詳細環境變量請參考 libpq-envars. 如果沒有設置環境變量且連接字符串也沒有提供該參數,   程序會 panic 崩潰退出, 字符串參數優先級高于環境變量.

完整 增刪改查 示例代碼

package main import (  database/sql   encoding/json   fmt  _  github.com/lib/pq   log  ) const ( // Initialize connection constants. HOST =  172.16.xx.xx  PORT = 31976 DATABASE =  postgres  USER =  postgres  PASSWORD =  xxx  ) func checkError(err error) { if err != nil { panic(err) } } type Db struct { db *sql.DB } //  創建表  func (this *Db) CreateTable() { //  以水果庫存清單表 inventory 為例  // Drop previous table of same name if one exists.  如果之前存在清單表,  則刪除該表  _, err := this.db.Exec( DROP TABLE IF EXISTS inventory;) checkError(err) fmt.Println(Finished dropping table (if existed) ) // Create table.  創建表,  指定 id, name, quantity(數量) 字段,  其中 id 為主鍵  _, err = this.db.Exec(CREATE TABLE inventory (id serial PRIMARY KEY, name VARCHAR(50), quantity INTEGER); ) checkError(err) fmt.Println(Finished creating table) } //  刪除表  func (this *Db) DropTable() { //  以水果庫存清單表 inventory 為例  // Drop previous table of same name if one exists.  如果之前存在清單表,  則刪除該表  _, err := this.db.Exec( DROP TABLE IF EXISTS inventory;) checkError(err) fmt.Println(Finished dropping table (if existed) ) } //  增加數據  func (this *Db) Insert() { // Insert some data into table.  插入 3 條水果數據  sql_statement :=  INSERT INTO inventory (name, quantity) VALUES ($1, $2);  _, err := this.db.Exec(sql_statement,  banana , 150) checkError(err) _, err = this.db.Exec(sql_statement,  orange , 154) checkError(err) _, err = this.db.Exec(sql_statement,  apple , 100) checkError(err) fmt.Println(Inserted 3 rows of data) } //  讀數據 / 查數據  func (this *Db) Read() { // 讀取數據  // Read rows from table. var id int var name string var quantity int sql_statement :=  SELECT * from inventory;  rows, err := this.db.Query(sql_statement) checkError(err) defer rows.Close() for rows.Next() { switch err := rows.Scan( id,  name,  quantity); err { case sql.ErrNoRows: fmt.Println( No rows were returned) case nil: fmt.Printf(Data row = (%d, %s, %d)\n , id, name, quantity) default: checkError(err) } } } //  更新數據  func (this *Db) Update() { // Modify some data in table. sql_statement :=  UPDATE inventory SET quantity = $2 WHERE name = $1;  _, err := this.db.Exec(sql_statement,  banana , 200) checkError(err) fmt.Println(Updated 1 row of data) } //  刪除數據  func (this *Db) Delete() { // Delete some data from table. sql_statement :=  DELETE FROM inventory WHERE name = $1;  _, err := this.db.Exec(sql_statement,  orange) checkError(err) fmt.Println(Deleted 1 row of data) } //  數據序列化為 Json 字符串,  便于人工查看  func Data2Json(anyData interface{}) string { JsonByte, err := json.Marshal(anyData) if err != nil { log.Printf( 數據序列化為 json 出錯:\n%s\n , err.Error()) return   } return string(JsonByte) } // 多行數據解析  func QueryAndParseRows(Db *sql.DB, queryStr string) []map[string]string { rows, err := Db.Query(queryStr) defer rows.Close() if err != nil { log.Printf( 查詢出錯:\nSQL:\n%s,  錯誤詳情 \n , queryStr, err.Error()) return nil } cols, _ := rows.Columns() // 列名  if len(cols)   0 { var ret []map[string]string // 定義返回的映射切片變量 ret for rows.Next() { buff := make([]interface{}, len(cols)) data := make([][]byte, len(cols)) // 數據庫中的 NULL 值可以掃描到字節中  for i, _ := range buff { buff[i] =  data[i] } rows.Scan(buff...) // 掃描到 buff 接口中,實際是字符串類型 data 中  // 將每一行數據存放到數組中  dataKv := make(map[string]string, len(cols)) for k, col := range data { // k 是 index,col 是對應的值  //fmt.Printf( %30s:\t%s\n , cols[k], col) dataKv[cols[k]] = string(col) } ret = append(ret, dataKv) } log.Printf(返回多元素數組:\n%s , Data2Json(ret)) return ret } else { return nil } } // 單行數據解析   查詢數據庫,解析查詢結果,支持動態行數解析  func QueryAndParse(Db *sql.DB, queryStr string) map[string]string { rows, err := Db.Query(queryStr) defer rows.Close() if err != nil { log.Printf( 查詢出錯:\nSQL:\n%s,  錯誤詳情 \n , queryStr, err.Error()) return nil } //rows, _ := Db.Query(SHOW VARIABLES LIKE  %data%) cols, _ := rows.Columns() if len(cols)   0 { buff := make([]interface{}, len(cols)) //  臨時 slice data := make([][]byte, len(cols)) //  存數據 slice dataKv := make(map[string]string, len(cols)) for i, _ := range buff { buff[i] =  data[i] } for rows.Next() { rows.Scan(buff...) // ... 是必須的  } for k, col := range data { dataKv[cols[k]] = string(col) //fmt.Printf(%30s:\t%s\n , cols[k], col) } log.Printf(返回單行數據 Map:\n%s , Data2Json(dataKv)) return dataKv } else { return nil } } func main() { // Initialize connection string.  初始化連接字符串,  參數包含主機, 端口, 用戶名, 密碼, 數據庫名,SSL 模式 ( 禁用), 超時時間  var connectionString string = fmt.Sprintf(host=%s port=%d user=%s password=%s dbname=%s sslmode=disable connect_timeout=3 , HOST, PORT, USER, PASSWORD, DATABASE) // Initialize connection object.  初始化連接對象,  驅動名為 postgres db, err := sql.Open(postgres , connectionString) defer db.Close() checkError(err) postgresDb := Db{ db: db, } err = postgresDb.db.Ping() // 連通性檢查  checkError(err) fmt.Println(Successfully created connection to database) postgresDb.CreateTable() // 創建表  postgresDb.Insert() // 插入數據  postgresDb.Read() // 查詢數據  QueryAndParseRows(postgresDb.db,  SELECT * from inventory;) // 直接查詢和解析多行數據  QueryAndParse(postgresDb.db,  SHOW DateStyle;) // 直接查詢和解析單行數據  postgresDb.Update() // 修改 / 更新數據  postgresDb.Read() postgresDb.Delete() // 刪除數據  postgresDb.Read() postgresDb.DropTable() }

執行 go run main.go 運行結果如下:

Successfully created connection to database Finished dropping table (if existed) Finished creating table Inserted 3 rows of data Data row = (1, banana, 150) Data row = (2, orange, 154) Data row = (3, apple, 100) 2020/12/15 22:13:33  返回多元素數組: [{id : 1 , name : banana , quantity : 150},{id : 2 , name : orange , quantity : 154},{id : 3 , name : apple , quantity : 100}] 2020/12/15 22:13:33  返回單行數據 Map: {DateStyle : ISO, MDY} Updated 1 row of data Data row = (2, orange, 154) Data row = (3, apple, 100) Data row = (1, banana, 200) Deleted 1 row of data Data row = (3, apple, 100) Data row = (1, banana, 200) Finished dropping table (if existed)

“如何理解 Golang 牽手 PostgreSQL 增刪改查 + 不寫結構快速掃描字段”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注丸趣 TV 網站,丸趣 TV 小編將為大家輸出更多高質量的實用文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-27發表,共計7358字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 成都市| 南汇区| 株洲市| 沙坪坝区| 晋城| 睢宁县| 枣强县| 福贡县| 库车县| 阜康市| 丽江市| 仙游县| 灌南县| 绥阳县| 萝北县| 大荔县| 黄山市| 水富县| 民丰县| 泰顺县| 青州市| 普格县| 北川| 乌兰察布市| 山西省| 灌云县| 巴彦淖尔市| 永胜县| 平南县| 安新县| 榆社县| 汽车| 剑川县| 乐至县| 无极县| 广南县| 图们市| 阿城市| 武义县| 巴里| 德庆县|