内置库可持久保存BTree,相当于Java的FileChannel和ByteBuffer

nicovank:

因此,我遵循CLRS算法,用Java编写了该持久性BTree。我曾经FileChannelByteBuffer树存储在一个文件,读取并在需要时写的节点。

我试图寻找如何在Go中存储这样的BTree的方法,然后发现了os.File,我认为可以将其与Java的用法相同FileChannel但是,我找不到的等效项ByteBuffer我看了看bytes.Buffer,我看到这是如何工作的,但它不具备ByteBuffer的方便putIntputDouble等...

我是否必须实现自己的那些功能才能将int和double转换为字节数组?我也看了看encoding.binary,但这看起来很麻烦。我知道我必须每次将变量编码为字节数组,然后将该字节数组复制到缓冲区。

在这种情况下,建议使用什么结构?

icza:

使用encoding/gob包装

使用该encoding/gob包,您可以将整个树序列化为一系列字节,并通过单个方法调用将它们反序列化。

请参阅以下示例:

type Node struct {
    Data     int
    Children []*Node
}

func (n *Node) String() string {
    buf := &bytes.Buffer{}
    buf.WriteString(fmt.Sprintf("Node[Data: %d, Children: [", n.Data))
    for i, v := range n.Children {
        if i > 0 {
            buf.WriteString(", ")
        }
        buf.WriteString(v.String())
    }
    buf.WriteString("]")
    return buf.String()
}

Node.String()方法不是必需的,我只是创建它来轻松打印/验证树。

现在使用gob序列化和反序列化树:

root := &Node{
    Data: 1,
    Children: []*Node{
        {Data: 2},
        {Data: 3},
    },
}
fmt.Println(root)

buf := &bytes.Buffer{}
if err := gob.NewEncoder(buf).Encode(root); err != nil {
    panic(err)
}

var root2 *Node
if err := gob.NewDecoder(buf).Decode(&root2); err != nil {
    panic(err)
}
fmt.Println(root2)

输出(在Go Playground上尝试):

Node[Data: 1, Children: [Node[Data: 2, Children: [], Node[Data: 3, Children: []]
Node[Data: 1, Children: [Node[Data: 2, Children: [], Node[Data: 3, Children: []]

在这里,我使用了内存中的缓冲区(bytes.Buffer),但是如果要保存到文件或从文件中加载,甚至不需要内存中的缓冲区,则可以直接将*os.File传递gob.NewEncoder()gob.NewDecoder()(因为*os.File实现了io.Readerio.Writer) 。

手动序列化/反序列化

还要注意,如果您不想(或无法)encoding/gob一步完成完整的序列化操作,则还可以使用binary.Write()binary.Read()函数直接写入文件或从文件中读取数据,而无需使用任何内存中的缓冲区。

请参见以下示例,对an int32float64value进行编码和解码

var i int32
var f float64

i, f = 1, 3.14

buf := &bytes.Buffer{}
if err := binary.Write(buf, binary.LittleEndian, i); err != nil {
    panic(err)
}
if err := binary.Write(buf, binary.LittleEndian, f); err != nil {
    panic(err)
}

var i2 int32
var f2 float64
if err := binary.Read(buf, binary.LittleEndian, &i2); err != nil {
    panic(err)
}
if err := binary.Read(buf, binary.LittleEndian, &f2); err != nil {
    panic(err)
}

fmt.Println(i2, f2)

输出(在Go Playground上尝试):

1 3.14

同样,您可以将文件直接传递给binary.Read()binary.Write()不是*bytes.Buffer

非二进制序列化

您还可以使用其他非二进制序列化格式,例如JSON。encoding/json软件包还可以通过一次调用对整个树进行序列化/反序列化。尽管在存储和速度方面使用JSON的性能较差,但是序列化的格式将更加人性化(更易于读取/编辑),并且与其他应用程序/技术兼容。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章