You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang Apache Arrow中使用datatype.go构建Schema及相关技术问题

Apache Arrow Go:非基础类型Schema构建与扩展类型使用

问题1:使用datatype.go中的类型构建Schema

datatype.go中的类型均实现了arrow.DataType接口,只是PrimitiveTypes提供了预定义实例,其他类型需自行创建结构体实例即可用于构建Schema。以布尔类型为例:

import "github.com/apache/arrow/go/v15/arrow"

func main() {
    schema := arrow.NewSchema(
        []arrow.Field{
            // 直接创建BooleanType实例作为字段类型
            {Name: "is_valid", Type: &arrow.BooleanType{}, Nullable: true},
            {Name: "log_count", Type: arrow.PrimitiveTypes.Uint32},
        },
        nil,
    )
}

类似的,StringType、BinaryType等非PrimitiveTypes预定义的类型,都可以通过直接实例化对应的结构体来使用。

问题2:Decimal类型的精度与刻度指定

Arrow Go中的Decimal128Type和Decimal256Type支持通过结构体参数指定精度(总位数)和刻度(小数点后位数),示例如下:

import "github.com/apache/arrow/go/v15/arrow"

func main() {
    // 创建精度为16、刻度为4的Decimal128类型
    decimalType := &arrow.Decimal128Type{
        Precision: 16, // 总位数
        Scale:     4,  // 小数点后位数
    }

    schema := arrow.NewSchema(
        []arrow.Field{
            {Name: "account_balance", Type: decimalType, Nullable: true},
        },
        nil,
    )
}

该类型可存储如123456789012.3456这类符合精度和刻度要求的数值。

问题3:扩展类型使用示例

扩展类型需实现arrow.ExtensionType接口,以下是基于FixedSizeBinary实现自定义UUID扩展类型的完整示例:

1. 定义扩展类型

import (
    "github.com/apache/arrow/go/v15/arrow"
    "github.com/apache/arrow/go/v15/arrow/array"
)

// UUIDType 自定义UUID扩展类型,基于16字节固定长度二进制
type UUIDType struct {
    arrow.FixedSizeBinaryType
}

// ExtensionName 返回扩展类型的唯一标识名称
func (t *UUIDType) ExtensionName() string {
    return "custom.uuid"
}

// ExtensionEquals 判断两个扩展类型是否等价
func (t *UUIDType) ExtensionEquals(other arrow.ExtensionType) bool {
    ot, ok := other.(*UUIDType)
    return ok && t.ByteWidth == ot.ByteWidth
}

// SerializeExtensionType 序列化扩展类型元数据(此处无需额外信息)
func (t *UUIDType) SerializeExtensionType() string {
    return ""
}

// DeserializeExtensionType 从存储类型和序列化信息恢复扩展类型
func (t *UUIDType) DeserializeExtensionType(storageType arrow.DataType, serialized string) arrow.ExtensionType {
    fsbType, ok := storageType.(*arrow.FixedSizeBinaryType)
    if !ok || fsbType.ByteWidth != 16 {
        panic("invalid storage type for UUID extension")
    }
    return &UUIDType{FixedSizeBinaryType: *fsbType}
}

// NewExtensionArray 创建对应扩展类型的数组实例
func (t *UUIDType) NewExtensionArray(data *array.Data) arrow.Array {
    return array.NewFixedSizeBinaryData(data) // 复用固定长度二进制数组的实现
}

2. 使用扩展类型构建Schema与记录

func main() {
    // 初始化UUID扩展类型
    uuidType := &UUIDType{
        FixedSizeBinaryType: arrow.FixedSizeBinaryType{ByteWidth: 16},
    }

    // 构建包含扩展类型的Schema
    schema := arrow.NewSchema(
        []arrow.Field{
            {Name: "user_uuid", Type: uuidType, Nullable: false},
            {Name: "user_name", Type: &arrow.StringType{}},
        },
        nil,
    )

    // 构建扩展类型数组
    uuidBuilder := array.NewFixedSizeBinaryBuilder(nil, uuidType)
    defer uuidBuilder.Release()
    // 示例UUID字节数据
    sampleUUID := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}
    uuidBuilder.Append(sampleUUID)

    // 构建字符串字段数组
    nameBuilder := array.NewStringBuilder(nil)
    defer nameBuilder.Release()
    nameBuilder.Append("john_doe")

    // 创建记录批次
    record := array.NewRecord(schema, []arrow.Array{uuidBuilder.NewFixedSizeBinaryArray(), nameBuilder.NewStringArray()}, 1)
    defer record.Release()

    // 打印记录信息
    println(record.String())
}

内容的提问来源于stack exchange,提问作者A Beginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:32:43