跳转到主要内容

类型转换

对于插入以及响应编组,客户端力求在接受变量类型方面尽可能灵活。在大多数情况下,ClickHouse 的列类型都存在对应的 Golang 类型,例如,UInt64 对应 uint64。这类逻辑映射应始终受到支持。如果变量或接收到的数据能够先完成转换,你也可以使用可插入列中或可用于接收响应的变量类型。客户端力求透明地支持这些转换,这样一来,用户在插入前无需先将数据精确转换到完全匹配的类型,同时也能在查询时实现灵活的编组。这种透明转换不允许出现精度损失。例如,不能使用 uint32 来接收来自 UInt64 列的数据。相反,只要满足格式要求,字符串就可以插入到 datetime64 字段中。 当前支持的基本类型转换见这里 这项工作仍在持续推进中,可分为插入 (Append/AppendRow) 和读取时 (通过 Scan) 两部分。如果你需要支持某种特定转换,请提交 issue。 标准的 database/sql 接口应支持与 ClickHouse API 相同的类型。也有少数例外,主要涉及复杂类型,相关内容已在下文各节中说明。与 ClickHouse API 类似,客户端在接受用于插入和响应编组的变量类型方面,也力求尽可能灵活。

复杂类型

Date/DateTime

ClickHouse Go client 支持 DateDate32DateTimeDateTime64 日期/日期时间类型。日期既可以以 2006-01-02 格式的字符串插入,也可以使用原生 Go 类型 time.Time{}sql.NullTime。DateTime 同样支持后两种类型,但字符串必须采用 2006-01-02 15:04:05 格式,并可选择附带时区偏移,例如 2006-01-02 15:04:05 +08:00。读取时也支持 time.Time{}sql.NullTime,以及任何实现了 sql.Scanner 接口的类型。 时区信息的处理方式取决于 ClickHouse 类型,以及该值是被插入还是读取:
  • DateTime/DateTime64
    • insert 时,值会以 UNIX timestamp 格式发送到 ClickHouse。如果未提供时区,客户端会假定使用客户端本地时区。time.Time{}sql.NullTime 也会据此转换为自 Unix 纪元起的时间戳。
    • select 时,返回 time.Time 值时,如果列设置了 timezone,则使用列的 timezone;否则使用 server 的 timezone。
  • Date/Date32
    • insert 时,将日期转换为 unix timestamp 时会考虑日期的 timezone;也就是说,在按日期存储之前,会先根据 timezone 进行偏移,因为 ClickHouse 中的 Date 类型本身不包含时区信息。如果字符串值中未指定这一信息,则会使用本地 timezone。
    • select 时,扫描到 time.Time{}sql.NullTime{} 实例中的日期值,返回时将不包含时区信息。

Time/Time64 类型

TimeTime64 列类型用于存储不包含日期部分的时刻值。两者都映射为 Go 的 time.Duration
  • Time 以秒级精度存储时刻。
  • Time64(precision) 支持子秒级精度 (类似于 DateTime64) ,其中 precision 的取值范围为 0–9。

Array

Array 应以切片形式插入。其元素的类型规则与基本类型一致,也就是说,在可能的情况下会进行类型转换。 在 Scan 时,应提供指向切片的指针。
完整示例

Map

应以 Golang map 的形式插入 Map,其中的键和值必须符合前文定义的类型规则。
完整示例
使用 database/sql API 时,Map 值必须严格指定类型,不能将 interface{} 用作值类型。例如,对于 Map(String,String) 字段,不能传入 map[string]interface{},而必须使用 map[string]string。不过,interface{} 类型的变量始终是兼容的,因此可用于更复杂的结构。完整示例

元组

Tuples 表示一组长度任意的列。这些列既可以显式命名,也可以仅指定类型,例如:
在这些方法中,命名元组的灵活性更高。未命名元组必须通过切片进行插入和读取,而命名元组还兼容 Map。
完整示例 注意:支持类型化的切片和 Map,前提是命名元组中的各个子列类型都相同。

Nested

Nested 字段等同于由命名元组组成的 Array。具体用法取决于用户是否将 flatten_nested 设置为 1 或 0。 将 flatten_nested 设置为 0 后,Nested 列会保持为单个元组数组。这样你就可以使用Map切片进行插入和读取,并支持任意层级的嵌套。映射中的键名必须与列名相同,如下例所示。 注意:由于这些Map表示的是元组,因此它们的类型必须为 map[string]interface{}。这些值目前没有强类型约束。
完整示例 - flatten_tested=0 如果 flatten_nested 使用默认值 1,嵌套列会被展平为独立的数组。因此,在插入和读取时需要使用嵌套切片。虽然任意级别的嵌套可能也可以工作,但这并不属于官方支持的范围。
完整示例 - flatten_nested=1 注意:Nested 列中的各列必须具有相同的维度。例如,在上面的示例中,Col_2_2Col_2_1 必须包含相同数量的元素。 由于其接口更直观,且官方支持嵌套,我们建议使用 flatten_nested=0

Geo 类型

客户端支持以下 Geo 类型:Point、Ring、LineString、Polygon、MultiPolygon 和 MultiLineString。这些类型在 Go 中通过 github.com/paulmach/orb 包来表示。
完整示例

UUID

github.com/google/uuid 包支持 UUID 类型。你也可以将 UUID 作为字符串,或作为任何实现了 sql.ScannerStringify 的类型进行发送和序列化。
完整示例

Decimal

由于 Go 没有内置的 Decimal 类型,我们建议使用第三方包 github.com/shopspring/decimal,以便在不修改原始查询的情况下原生处理 Decimal 类型。
你可能会想改用 Float,以避免引入第三方依赖。不过请注意,在需要精确值时,不建议在 ClickHouse 中使用 Float 类型如果你仍然选择在客户端使用 Go 的内置 Float 类型,则必须在 ClickHouse 查询中使用 toFloat64() 函数其变体 显式将 Decimal 转换为 Float。请注意,这种转换可能会导致精度损失。
完整示例

Nullable

Go 中的 Nil 值表示 ClickHouse 的 NULL。如果某个字段声明为 Nullable,就可以使用它。在写入时,对于列的普通版本和 Nullable 版本,都可以传入 Nil。对于前者,会写入该类型的默认值,例如 string 类型的空字符串。对于 Nullable 版本,则会在 ClickHouse 中存储 NULL 值。 在扫描时,用户必须传入一个支持 nil 的类型指针,例如 *string,才能表示 Nullable 字段的 nil 值。在下面的示例中,col1 是 Nullable(String),因此接收的是 **string。这样就可以表示 nil。
完整示例 该客户端还额外支持 sql.Null* 类型,例如 sql.NullInt64。这些类型与对应的 ClickHouse 类型兼容。

大整数

超过 64 位的数值类型使用 Go 原生的 big 包表示。
完整示例

BFloat16

BFloat16 是一种用于机器学习场景的 16 位 brain float 类型。在 Go 中,BFloat16 值以 float32 形式插入和扫描。Nullable 变体使用 sql.NullFloat64
完整示例

QBit

QBit 是一种 Experimental 列类型,用于以位切片格式存储嵌入向量,并针对向量相似性搜索进行了优化。它要求启用 allow_experimental_qbit_type 设置。 在 Go 中,QBit(Float32, N) 列会以 []float32 的形式插入和扫描,其中 N 为向量维度。
完整示例
最后修改于 2026年7月1日