我一直在学习数据库,并希望出于学习目的而非生产目的实施一个数据库。我有一个定义的模式:type Row struct { ID int32 Username string Email string}现在,目前,我能够以仅附加的方式将这种类型的结构编码到文件中。//Just to show i use a file for the encoding, it has missing details.func NewEncoder(db *DB) *gob.Encoder{ return gob.NewEncoder(db.File)}func SerializeRow(r Row, encoder *gob.Encoder, db *DB) { err := encoder.Encode(r) if err != nil { log.Println("encode error:", err) }}现在,通过简单地解码整个文件来模仿“选择”语句相对容易gob.decodefunc DeserializeRow(decoder *gob.Decoder, db *DB){ var rows Row db.File.Seek(0, 0) err := decoder.Decode(&rows) for err == nil { if err != nil { log.Println("decode error:", err) } fmt.Printf("%d %s %s\n", rows.ID, rows.Username, rows.Email) err = decoder.Decode(&rows) }}我当前的问题是,我希望能够根据 ID 检索特定行。我知道sqlite使用 4kb 分页,在某种意义上,序列化的行占据一个“页面”,即。4KB 直到一个页面不能再容纳它们,然后创建另一个。我如何gob以最简单和惯用的方式模仿这种行为?
1 回答

阿晨1998
TA贡献2037条经验 获得超6个赞
一个 Gob 流可能包含类型定义和解码指令,所以你不能寻找一个 Gob 流。您只能从头开始阅读,直到找到所需内容为止。
Gob 流完全不适合需要跳过元素的数据库存储格式。
您可以创建一个新的编码器并分别序列化每个记录,在这种情况下您可以跳过元素(通过维护一个文件索引来存储哪个记录从哪个位置开始),但这将是非常低效和冗余的(如链接答案中所述,当您写入更多相同类型的值时,速度和存储成本会摊销,并且总是创建新的编码器会失去这种收益)。
更好的方法是不encoding/gob
为此使用,而是定义自己的格式。为了有效地支持搜索(select
),您必须在可搜索的列/字段上构建某种索引,否则您仍然需要执行全表扫描。
- 1 回答
- 0 关注
- 88 浏览
添加回答
举报
0/150
提交
取消