您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何使用go連接clickhouse”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“如何使用go連接clickhouse”文章能幫助大家解決問題。
近段時間業務在一個局點測試clickhouse,用java寫的代碼在環境上一直連接不上clickhouse服務,報錯信息也比較奇怪,No client available
,研發查了一段時間沒查出來,讓運維這邊繼續查:
運維同學查了各種監聽配置,防火墻這些,都沒什么問題,但是沒有明確證據能夠提供證明通過http方式能訪問到數據庫,時間拖得比較久,項目上就急了,讓盡快找到問題,所以就用go寫了個小工具拉到集群上試試看8123這個端口到底能不能正常提供服務。
先安裝必要的庫,clickhouse官方提供了2個版本的庫,v1和v2,v1版本已經明確不會繼續更新了,所以用新不用舊哈,可以用官方庫的方式或者用dsn的方式,這個我下面一起說,安裝庫的命令:
go get github.com/ClickHouse/clickhouse-go/v2
編寫結構體,存放基本信息:
type Clickhouse struct { Host string // 服務端主機 Port int // 端口 DB string // 數據庫 User string // 用戶名 Password string // 密碼 Connection *sql.DB // 建立連接后存放連接 Rows *sql.Rows // 運行sql后的結果存放 }
Connection
主要是用來建立連接后把相關信息存放,這樣方便繼續調用其他的方法,因為我的主要目的是測試數據庫能否連通和運行Sql,所以這里Rows
用來存放測試的select語句的結果。
這塊沒什么好說的,連接的參數直接從命令行讀取,用flag包就好:
var ( host = flag.String("host", "localhost", "clickhouse host") port = flag.Int("port", 8123, "clickhouse port") user = flag.String("user", "default", "clichouse user") pass = flag.String("password", "", "clickhouse password") db = flag.String("db", "default", "clickhouse database") query = flag.String("query", "show tables", "query you will run") mode = flag.String("mode", "driver", "driver or dsn") )
前面幾個參數不用解釋,主要是query
和mode
,query
是要運行的sql語句,我們默認就認為跑的是select語句,然后是mode
,允許選擇模式,用戶可以使用driver
或者dsn
兩種模式進行連接,我寫了兩個不同的方法,其實也可以在一個Connect方法里做判斷,看個人習慣;
接下來我們建立數據庫連接:
// func (c *Clickhouse) Conn() { c.Connection = clickhouse.OpenDB(&clickhouse.Options{ Addr: []string{fmt.Sprintf("%s:%d", c.Host, c.Port)}, Auth: clickhouse.Auth{ Database: c.DB, Username: c.User, Password: c.Password, }, Settings: clickhouse.Settings{ "max_execution_time": 60, }, DialTimeout: 5 * time.Second, Compression: &clickhouse.Compression{ Method: clickhouse.CompressionBrotli, Level: 5, }, // 必須添加協議方式 Protocol: clickhouse.HTTP, }) } func (c *Clickhouse) ConnDsn() { conn, err := sql.Open("clickhouse", fmt.Sprintf("http://%s:%d/%s?username=%s&password=%s", c.Host, c.Port, c.DB, c.User, c.Password)) if err != nil { log.Printf("Connect to the server failed, %s.\n", err.Error()) return } c.Connection = conn }
參考官網的實例,實現兩種連接方式,關閉方法就直接把sql.DB和sql.Rows都關閉就可以了:
func (c *Clickhouse) Close() { c.Connection.Close() c.Rows.Close() }
查詢使用Query方法進行:
func (c *Clickhouse) Select(query string) { rows, err := c.Connection.Query(query) if err != nil { log.Printf("Query select failed, %s.\n", err.Error()) return } c.Rows = rows }
查詢的結果我保存到Rows里,方便后面的解析
比較麻煩的就是結果的解析了,用過database/sql
庫的哥們都知道,這個庫只提供了基礎的一些接口,查詢出來一般用Scan去獲取數據,用法類似這樣:
問題就在于,Scan要指定和sql查詢出來一樣多的變量,對于我們這個小工具來說,sql是不一定的,所以查詢出來的字段數量肯定yes不定的,如何動態處理這個問題,肯定是不能直接寫一個結構體解決的,先看我的代碼:
func (c *Clickhouse) Show() { cols, err := c.Rows.Columns() if err != nil { log.Printf("Failed to get table columns, %s.\n", err.Error()) return } // 一行數據,使用any是為了避開數據類型的問題 var rows = make([]any, len(cols)) // 存實際的值,是byte數組,長度以列的數量為準 var values = make([][]byte, len(cols)) for i := 0; i < len(cols); i++ { rows[i] = &values[i] } // 打印表頭 fmt.Println(strings.Join(cols, ",")) for c.Rows.Next() { if err = c.Rows.Scan(rows...); err != nil { fmt.Println(err) return } var vString []string for _, v := range values { vString = append(vString, string(v)) } // 逐行打印出來 fmt.Println(strings.Join(vString, ",")) } }
大概思路是這樣:
Scan需要傳入每個用來綁定單行數據值的變量,所以values是實際存儲數據的byte數組,然后把數組的每個元素的地址再存入到rows數組中;
現在可以用rows[index]這樣的方式來訪問values中的值了,把rows直接作為入參傳入到Scan,在每次循環中,把values的值轉成逗號分割的字符串,直接打印
OK,現在邏輯完成了,我們運行測試一下,
go run main.go -host hostname -password paswword -query "select * from clusters" -db system -mode dsn
只查詢2個字段,2行數據:
關于“如何使用go連接clickhouse”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。