Go 用于持久化BTree的内置库,相当于Java';s`FileChannel`和`ByteBuffer`

Go 用于持久化BTree的内置库,相当于Java';s`FileChannel`和`ByteBuffer`,go,serialization,persistence,b-tree,Go,Serialization,Persistence,B Tree,因此,我按照CLRS算法,用Java编写了这个持久化BTree。 我使用FileChannel和ByteBuffer将树存储在文件中,在需要时读取和写入节点 我试着寻找如何在Go中存储这样一个BTree,发现了os.File,我认为它可以与Java的FileChannel一样使用。 但是,我找不到ByteBuffer的等价物。我查看了bytes.Buffer,了解了它的工作原理,但是它没有ByteBuffer的方便putin,putDouble,等等 我必须自己实现这些函数才能将整数和双精度数转

因此,我按照CLRS算法,用Java编写了这个持久化BTree。 我使用
FileChannel
ByteBuffer
将树存储在文件中,在需要时读取和写入节点

我试着寻找如何在Go中存储这样一个BTree,发现了
os.File
,我认为它可以与Java的
FileChannel
一样使用。 但是,我找不到
ByteBuffer
的等价物。我查看了
bytes.Buffer
,了解了它的工作原理,但是它没有
ByteBuffer
的方便
putin
putDouble
,等等

我必须自己实现这些函数才能将整数和双精度数转换为字节数组吗?我还研究了
编码.binary
,但这看起来非常麻烦。我知道每次都必须将变量编码为字节数组,然后将该字节数组复制到缓冲区


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

请注意,
bytes.Buffer
实现了
io.Writer
接口。因此,您可以使用:


format
string参数可用于将整数和双倍数直接写入缓冲区。有关详细信息,请参见。

请注意,
bytes.Buffer
实现了
io.Writer
接口。因此,您可以使用:

format
string参数可用于将整数和双倍数直接写入缓冲区。有关详细信息,请参阅。

使用
编码/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)
输出(在上尝试):

在这里,我使用了内存缓冲区(),但如果您想保存到文件或从文件加载,甚至不需要内存缓冲区,您可以直接将值传递给and(因为
*os.file
同时实现and)

手动序列化/反序列化 还请注意,如果您不想(或不能)使用
编码/gob
一步完成序列化,也可以使用和函数直接写入/读取文件,而不使用任何内存缓冲区

请参见此示例编码和解码
int32
float64
值:

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)
输出(在上尝试):

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

非二进制序列化 您还可以使用其他非二进制序列化格式,如JSON。 该包还可以通过一个调用序列化/反序列化整个树。虽然使用JSON在存储和速度方面性能较差,但序列化格式更人性化(更可读/可编辑),并且与其他应用程序/技术兼容

使用
编码/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)
输出(在上尝试):

在这里,我使用了内存缓冲区(),但如果您想保存到文件或从文件加载,甚至不需要内存缓冲区,您可以直接将值传递给and(因为
*os.file
同时实现and)

手动序列化/反序列化 还请注意,如果您不想(或不能)使用
编码/gob
一步完成序列化,也可以使用和函数直接写入/读取文件,而不使用任何内存缓冲区

请参见此示例编码和解码
int32
float64
值:

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)
输出(在上尝试):

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

非二进制序列化 您还可以使用其他非二进制序列化格式,如JSON。
该包还可以通过一个调用序列化/反序列化整个树。虽然使用JSON在存储和速度方面性能较差,但序列化格式更人性化(更可读/可编辑),并且与其他应用程序/技术兼容

如果你阅读一些与你正在尝试的类似的Go代码,你可能会发现Go更容易学习,而不是看Java并试图在Go中复制它的行为。icza提供了一个非常完整的答案!如果你阅读一些与你正在尝试的类似的Go代码,你可能会发现Go更容易学习,而不是看Java并试图在Go中复制它的行为。icza提供了一个非常完整的答案!