Go 用于持久化BTree的内置库,相当于Java';s`FileChannel`和`ByteBuffer`
因此,我按照CLRS算法,用Java编写了这个持久化BTree。 我使用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,等等 我必须自己实现这些函数才能将整数和双精度数转
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提供了一个非常完整的答案!