【Go】实操使用go连接clickhouse

news2025/1/12 23:43:46

前言

近段时间业务在一个局点测试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")
)

前面几个参数不用解释,主要是querymodequery是要运行的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行数据:

在这里插入图片描述

结语

完成,然后把工具放到生产环境一测试,查询都正常,这下开发哥们要继续查他的程序问题了,😃,运维甩锅成功🎉🎉🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/156553.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OAuth 2.0授权框架详解

简介 在现代的网站中&#xff0c;我们经常会遇到使用OAuth授权的情况&#xff0c;比如有一个比较小众的网站&#xff0c;需要用户登录&#xff0c;但是直接让用户注册就显得非常麻烦&#xff0c;用户可能因为这个原因而流失&#xff0c;那么该网站可以使用OAuth授权&#xff0…

FactoryBean和BeanFactory的区别

1. 前言 “BeanFactory和FactoryBean的区别是什么&#xff1f;&#xff1f;&#xff1f;” 这是Spring非常高频的一道面试题&#xff0c;BeanFactory是Spring bean容器的顶级接口&#xff0c;负责创建和维护容器内所有的bean对象。而FactoryBean是用来创建一类bean的接口&…

数字新基建之数据云

自2021年“新基建”概念火爆以来&#xff0c;相关的政策和技术都不断跟进和发展&#xff0c;由于“新基建”本质上是基础设施向数字化、智能化、网络化方向发展&#xff0c;因此更多的科技领域从业者和投资者都将其称为“数字新基建”。而数据库、数据仓库、大数据平台和数据云…

C语言:整数的存储方式

整数的存储方式 char类型在存储时是按照ASCII码值进行存储&#xff0c;存储方式与整型一致 有符号数与无符号数 char一个字节signed charunsigned char int四个字节signed intunsigned int 各种类型数据均分为有符号和无符号类型&#xff0c;当定义一个int类型或char类型的数…

备库为什么会延迟好几个小时?

在上一篇文章中,我和你介绍了几种可能导致备库延迟的原因。你会发现,这些场景里,不论是偶发性的查询压力,还是备份,对备库延迟的影响一般是分钟级的,而且在备库恢复正常以后都能够追上来。 但是,如果备库执行日志的速度持续低于主库生成日志的速度,那这个延迟就有可能…

百度搜索留痕推广资源整理如何收录排名的?

每日分享&#xff1a;百度对图文类内容的优质标准 &#xff08;1&#xff09;文字的字体、字号与间距需要适配网页&#xff0c;文档分段合理&#xff0c;结构有序&#xff0c;阅读体验舒适。 &#xff08;2&#xff09;在文章中使用小标题准确概括段意&#xff0c;通过加粗、…

vue3 setup语法糖父子组件传值,让女友看得明明白白

前言 最近在想做个cloud项目,gitee上找了个模板项目&#xff0c;前端使用到vue3 typeScript&#xff0c;最近使用到vue3 的父子组件之间的传值&#xff0c;顺便学习一下&#xff0c;在此总结一下&#xff0c;若有不足之处&#xff0c;望大佬们可以指出。 vue3官网&#xff1a…

栈--专题讲解

文章目录基本概念模拟栈数据结构-栈&#xff1a;stack头文件定义基本操作实例&#xff1a;火车进栈题目大意解题思路AC代码基本概念 栈的定义 栈(stack)是限定仅在表尾进行插入或者删除的线性表。对于栈来说&#xff0c;表尾端称为栈顶&#xff08;top&#xff09;&#xff0c…

web服务器----基于http协议搭建的静态网站详解

一&#xff0c;WWW的简介 1、什么是 www www 是 world wide web 的缩写&#xff0c;也就是全球信息广播的意思。通常说的上网就是使用 www 来查询用户所需要的信息。www 可以结合文字、图形、影像以及声音等多媒体&#xff0c;并通过可以让鼠标单击超链接的方式将信息以 Inter…

Docker容器搭建及基本使用

一、安装环境 操作系统&#xff1a;CentOS 7&#xff08;建议用7或以上&#xff0c;因为6版本有部分功能不兼容&#xff09; 二、Docker安装 1、卸载旧版本 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrota…

linux修改密码报错‘Authentication token manipulation error‘

本次事故使用操作系统为centos7 1、报错起因&#xff1a; 利用chage设置root用户密码定期更换后&#xff0c;到期之后登录系统&#xff0c;输入密码之后&#xff0c;提示要改密码&#xff0c;输入新密码之后&#xff0c;报错 ‘Authentication token manipulation error’ &a…

【k8s系列】gvisor安装与containerd集成

文章目录安装与containerd集成下发runtimeclass资源修改containerd配置文件准备pod的yaml文件参考资料author: ningan123date: ‘2023-01-11 21:23’updated: ‘2023-01-11 21:31’安装 安装地址&#xff1a;Installation - gVisor ARCH$(uname -m)URLhttps://storage.googlea…

Gotify <2.2.3 存在反射型 XSS 漏洞(MPS-2023-0815)

漏洞描述 Gotify 是 Go 语言开发的开源组件&#xff0c;用作于发送和接收消息的服务器。 由于 2.2.3 之前版本的 Gotify 使用具有反射型 XSS 漏洞版本的 swagger-ui 生成文档&#xff0c;当用户访问 Gotify /docs 页面时存在反射型 XSS 漏洞。 攻击者可诱导 Gotify 用户点击…

【学习笔记】【Pytorch】四、torchvision中的数据集使用

【学习笔记】【Pytorch】四、torchvision中的数据集使用学习地址主要内容一、datasets模块介绍二、datasets.CIFAR10类的使用1.使用说明2.代码实现学习地址 PyTorch深度学习快速入门教程【小土堆】. 主要内容 一、datasets模块介绍 介绍&#xff1a;一些加载数据的函数及常用…

P6:DataLoader的使用

1、准备数据集&#xff08;测试集&#xff09; import torchvisiontest_data torchvision.datasets.CIFAR10(./dataset, trainFalse, transformtorchvision.transforms.ToTensor()) 注意数据集中的图片是PIL的格式&#xff0c;需要格式转换。 2、使用DataLoader from torch…

HBase数据库总结(一)

1、 HBase的特点是什么&#xff1f;HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统&#xff0c;HBase不同于一般的关系数据库&#xff0c;它是一个适合于非结构化数据存储的数据库。1&#xff09;大&#xff1a;一个表可以有数十亿行&#xff0c;上百万列2&…

测试开发基础|一文搞定计算机网络(一)

计算机网络知识对测试人员来说是非常重要的基础技能。无论是在平时测试工作中&#xff08;比如接口测试&#xff09;&#xff0c;还是测试技术面试时&#xff0c;都会经常涉猎。很多基础薄弱的同学靠临时抱佛脚突击搜索学习&#xff0c;对系统知识和重点难点的理解总是不够透彻…

认证授权-SpringSecurity

认证授权-SpringSecurity 1. 认证授权概述 1.1 认证授权概念 1.1.1 认证 在互联网中&#xff0c;我们每天都会使用到各种各样的 APP 和网站&#xff0c;在使用过程中通常还会遇到需要注册登录的情况&#xff0c;输入你的用户名和密码才能正常使用&#xff0c;也就是说成为这…

uniapp引入vantweapp踩坑笔记

vue-cli创建uniapp项目引入vantweapp踩坑笔记 uni-app中引入vantweappvue-cli创建uniapp项目引入vantweapp踩坑笔记一、环境准备二、项目搭建三、引入vant第一种方式第二种方式一、环境准备 我用的环境分别是 软件名称版本号下载命令\链接检查是否成功卸载命令Vue-clivue/cli…

JavaScript中的重要概念

JavaScript中的重要概念 1、标识符 标识符&#xff08;Identifier&#xff09;就是名字。JavaScript 中的标识符包括变量名、函数名、参数名、属性名、类名等。 合法的标识符应该注意以下强制规则&#xff1a; 第一个字符必须是字母、下划线&#xff08;_&#xff09;或美元…