如何使用 GO 语言读取可能是两种不同数据类型之一的 HDF5 属性?

How do I read an HDF5 attribute which could be one of two different data types, using the GO language?

作为评估项目的一部分,我正在将现有的 C++ 应用程序移植到 GO。作为其中的一部分,我需要读取两个数据集属性,这些属性在一些文件中存储为双精度,在一些文件中存储为浮点数。我用来处理这个问题的 C++ 代码如下所示(我们在 Debian Linux 上使用 libhdf5-cpp-100)。

const auto att = dataSet.openAttribute(attributeName);
if (att.getDataType() == H5::PredType::NATIVE_DOUBLE) {
    att.read(att.getDataType(), &attributeValue);
}
else if (att.getDataType() == H5::PredType::NATIVE_FLOAT) {
    float temp = 0.F;
    att.read(att.getDataType(), &temp);
    attributeValue = static_cast<double>(temp);
}
else {
    // we throw an exception indicating we don't support the type
}

我的问题是我在用 GO 编写等价物时遇到了问题。 (我正在使用 "gonum.org/v1/hdf5" 包。)读取方法似乎很简单:

func (s *Attribute) Read(data interface{}, dtype *Datatype) error

但我正在努力确定要传递什么作为数据类型,因为属性类型似乎没有 GetDataType 方法。我看到的最接近的是:

func (s *Attribute) GetType() Identifier

但这不是 return 数据类型,它 return 是标识符。我在假设给定标识符我可以确定数据类型的情况下尝试了以下比较:

if attr.GetType().ID() == hdf5.T_NATIVE_DOUBLE.ID() {
    // handle as a double
}

但这不起作用。从 GetType() 得到的 ID return 与双精度型或浮点型的 ID 不同。

我已经浏览了 https://godoc.org/gonum.org/v1/hdf5 上的在线文档,但无法找到解决我的问题的方法。 (或任何使用 GO 读取 HDF5 属性的示例。)

有没有人设法做到这样的事情?或者大多数示例只是假设类型而不是查询类型?

我已经证实了我的怀疑,现在有了正确的答案。根本问题是我在使用 C++ API 时出错(在某些情况下这会导致只写 1/2 的双精度数),而我实际上是在尝试在 GO 中重复该错误。其实解决方法很简单。

传递到属性 read 方法中的属性类型不是属性的类型,而是存储在内存中时您希望转换成的类型。这意味着我的 C++ 代码应该简单得多,因为不需要检查属性类型,也不需要 static_cast 结果。要读取和存储属性值,依靠 HDF5 执行转换并在属性不可转换为双精度值时抛出合适的异常,非常简单

const auto att = dataSet.openAttribute("my attribute name");
att.read(H5::PredType::NATIVE_DOUBLE, &attributeValue);

GO 版本的工作量更大,因为我们必须手动管理对象生命周期和错误条件,但就在这里。 (请注意,我假设“...处理错误...”也涉及提前退出,否则需要额外的 if 语句来检查 att 是否为 nil。)

att, err := dataSet.OpenAttribute("my attribute name")
if err != nil {
    ...handle the error...
}

err = att.Read(&attributeValue, hdf5.T_NATIVE_DOUBLE)
if err != nil {
    ...handle the error...
}

err = att.Close()
if err != nil {
    ...handle the error...
}