gob 解码器 returns 仅数组中的第一个元素

gob decoder returns only first element in the array

所以我试图创建一个模拟数据库,在当前的实现中,我试图制作一个 insertselect 插入行和 select return 是他们。我决定使用 bytes.Buffer 来帮助维护一个内存块,我可以在其中插入一行行,并在调用 select 时反序列化该内存块,但似乎 select 只是 returns 第一行而不是传递给数组的所有行。

main.go


func main() {
    inputBuffer := compiler.NewInputBuffer()
    scanner := bufio.NewScanner(os.Stdin)
    for {
        PrintPrompt()
        scanner.Scan()
        command := scanner.Text()
        inputBuffer.Buffer = command

        if strings.HasPrefix(inputBuffer.Buffer, ".") {
            switch compiler.DoMetaCommand(inputBuffer) {
            case compiler.MetaCommandSuccess:
                continue
            case compiler.MetaCommandUnrecognizedCommand:
                fmt.Printf("Unrecognized command %q \n", inputBuffer.Buffer)
                continue
            }
        }

        var statement compiler.Statement
        switch compiler.PrepareStatement(inputBuffer, &statement) {
        case compiler.PrepareSuccess:

        case compiler.PrepareUnrecognizedStatement:
            fmt.Printf("Unrecognized command at start of %q \n", inputBuffer.Buffer)
            continue

        case compiler.PrepareSyntaxError:
            fmt.Println("Syntax error. Could not parse statement.")
            continue
        }

        compiler.ExecuteStatement(statement)
        fmt.Println("Executed")

    }
}

func PrintPrompt() {
    fmt.Printf("db > ")
}

以上是负责收集用户输入等的代码

package compiler

import (
    "bytes"
    "log"
    "os"
    "strconv"
    "strings"
)


type Row struct {
    ID       int32
    Username string
    Email    string
}



type Statement struct {
    RowToInsert Row
    Type        StatementType
}

var (
    RowsTable       = make([]Row, 0)
    RowsTableBuffer bytes.Buffer
)

func DoMetaCommand(buffer InputBuffer) MetaCommandResult {
    if buffer.Buffer == ".exit" {
        os.Exit(0)
    } else {
        return MetaCommandUnrecognizedCommand
    }
    return MetaCommandSuccess
}

func PrepareStatement(buffer InputBuffer, statement *Statement) PrepareResult {
    if len(buffer.Buffer) > 6 {
        bufferArguments := strings.Fields(buffer.Buffer)
        if bufferArguments[0] == "insert" {
            statement.Type = StatementInsert
            if len(bufferArguments) < 4 {
                return PrepareSyntaxError
            } else {
                i, err := strconv.Atoi(bufferArguments[1])
                if err != nil {
                    log.Printf("%q is not a valid id\n", bufferArguments[1])
                    return PrepareSyntaxError
                } else {
                    statement.RowToInsert.ID = int32(i)
                }
                statement.RowToInsert.Username = bufferArguments[2]
                statement.RowToInsert.Email = bufferArguments[3]
            }
            RowsTable = append(RowsTable, statement.RowToInsert)
            
            return PrepareSuccess
        }
    }

    if buffer.Buffer == "select" {
        statement.Type = StatementSelect
        return PrepareSuccess
    }

    return PrepareUnrecognizedStatement
}

func ExecuteStatement(statement Statement) {
    switch statement.Type {
    case (StatementInsert):
        SerializeRow(RowsTable)
    case (StatementSelect):
        DeserializeRow()
    }
}

上面的代码用于解析条目并将其附加到语句中,根据关键字,它可以是 insertselect [取出用于定义枚举的代码并保留核心逻辑]


func SerializeRow(r []Row) {
    encoder := gob.NewEncoder(&RowsTableBuffer)
    err := encoder.Encode(r)
    if err != nil {
        log.Println("encode error:", err)
    }
}

func DeserializeRow() {
    var rowsBuffer = RowsTableBuffer
    rowsTable := make([]Row, 0)
    decoder := gob.NewDecoder(&rowsBuffer)
    err := decoder.Decode(&rowsTable)
    if err != nil {
            log.Println("decode error:", err)
        }
    fmt.Println(rowsTable)
}

所以上面的代码使用全局 buffer,其中 PrepareStatement() 中追加的 slice 将在 insert 完成后进行编码。 select 应该 return 所有行的切片,但出于某种原因只是 return 是第一个元素。

示例(在终端中): 如果我插入 2 个: db > insert 1 john c@mail.com db > insert 2 collins k@mail.com

然后我做一个select: select => 它 return 仅 [{1 john c@mail.com}]

这里有什么我遗漏的吗?感谢您的支持。

所以答案很简单。我们在 SerializeRow 函数中创建了一个新的 encoder 而不是创建它一次。我们把它从函数中拉出来,创建了一个全局的。

var (
    encoder = gob.NewEncoder(&RowsTableBuffer)
    decoder = gob.NewDecoder(&RowsTableBuffer)
)

func SerializeRow(r Row) {
    err := encoder.Encode(r)
    if err != nil {
        log.Println("encode error:", err)
    }

}

func DeserializeRow() {

    var rows Row

    err := decoder.Decode(&rows)

    for err == nil {
        if err != nil {
            log.Fatal("decode error:", err)
        }
        fmt.Printf("%d %s %s\n", rows.ID, rows.Username, rows.Email)
        err = decoder.Decode(&rows)

    }

}