Golang处理ClickHouse Decimal类型

在使用Golang处理ClickHouse的Decimal类型时遇到一些问题。官方driver在Scan时会将Decimal转为float64,导致精度丢失。尝试过用sql.RawBytes接收,但后续处理比较麻烦。请问有没有更好的方法能完整保留Decimal的精度?或者是否有推荐的第三方库可以正确处理这种类型?

2 回复

使用Go处理ClickHouse的Decimal类型时,推荐使用clickhouse-go驱动。可通过sql.RawBytes接收数据,再转换为字符串或自定义结构体处理。注意精度和标度设置,避免溢出。

更多关于Golang处理ClickHouse Decimal类型的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中处理ClickHouse的Decimal类型时,通常使用clickhouse-go驱动。以下是关键步骤和示例代码:

1. 安装驱动

go get github.com/ClickHouse/clickhouse-go/v2

2. 代码示例

package main

import (
	"context"
	"database/sql"
	"fmt"
	"log"

	_ "github.com/ClickHouse/clickhouse-go/v2"
)

func main() {
	// 连接ClickHouse
	conn, err := sql.Open("clickhouse", "tcp://localhost:9000?username=default&password=")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// 创建测试表(包含Decimal字段)
	_, err = conn.Exec(`
		CREATE TABLE IF NOT EXISTS decimal_test (
			id UInt32,
			amount Decimal(18, 4)
		) ENGINE = Memory
	`)
	if err != nil {
		log.Fatal(err)
	}

	// 插入数据
	tx, _ := conn.Begin()
	stmt, _ := tx.Prepare("INSERT INTO decimal_test (id, amount) VALUES (?, ?)")
	
	// 使用字符串或float64传递Decimal值
	_, err = stmt.Exec(1, "12345.6789")  // 字符串形式
	_, err = stmt.Exec(2, 98765.4321)    // float64形式
	
	if err != nil {
		log.Fatal(err)
	}
	tx.Commit()

	// 查询数据
	rows, err := conn.Query("SELECT id, amount FROM decimal_test")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var (
			id     uint32
			amount string // Decimal类型建议用字符串接收
		)
		if err := rows.Scan(&id, &amount); err != nil {
			log.Fatal(err)
		}
		fmt.Printf("ID: %d, Amount: %s\n", id, amount)
	}
}

3. 重要说明

  1. 精度定义Decimal(precision, scale)中precision是总位数,scale是小数位数
  2. 数据传递
    • 写入时支持字符串、float64或big.Int
    • 读取时建议用string接收避免精度丢失
  3. 类型映射
    • ClickHouse Decimal → Go string/float64
    • 大数值务必使用字符串避免精度问题

4. 处理建议

  • 金融等精度敏感场景始终使用字符串传输
  • 可自定义类型实现更精确的映射:
type Decimal string

func (d *Decimal) Scan(value interface{}) error {
    *d = Decimal(fmt.Sprint(value))
    return nil
}

使用此方案可确保Decimal数据在Golang和ClickHouse间准确传输。

回到顶部