为了账号安全,请及时绑定邮箱和手机立即绑定

使用 gob 序列化到磁盘后检索

使用 gob 序列化到磁盘后检索

Go
POPMUISE 2022-12-05 11:18:42
我一直在学习数据库,并希望出于学习目的而非生产目的实施一个数据库。我有一个定义的模式: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),您必须在可搜索的列/字段上构建某种索引,否则您仍然需要执行全表扫描。


查看完整回答
反对 回复 2022-12-05
  • 1 回答
  • 0 关注
  • 88 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号