gob解码器只返回数组中的第一个元素。

huangapple go评论117阅读模式
英文:

gob decoder returns only first element in the array

问题

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

上面的代码负责收集用户输入等。

以下是负责解析用户输入并将条目附加到语句中的代码,根据关键字,它可以是insertselect(已删除定义枚举的代码,只保留核心逻辑)。

代码使用全局的buffer,在PrepareStatement()中附加的slice将在执行insert后进行编码。select应该返回所有行的slice,但出于某种原因只返回第一个元素。

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

然后我进行一个选择:
select
=> 它只返回[{1 john c@mail.com}]

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

英文:

So I was trying to create a mock DB, and in the current implementation, I am trying to make an insert and select which insert rows and select returns them. I decided to use a bytes.Buffer to help maintain a memory block I could insert a slice of rows in, and deserialize that memory block when I call select but it seems select just returns the first row instead of all the rows passed to the array.

main.go

  1. func main() {
  2. inputBuffer := compiler.NewInputBuffer()
  3. scanner := bufio.NewScanner(os.Stdin)
  4. for {
  5. PrintPrompt()
  6. scanner.Scan()
  7. command := scanner.Text()
  8. inputBuffer.Buffer = command
  9. if strings.HasPrefix(inputBuffer.Buffer, ".") {
  10. switch compiler.DoMetaCommand(inputBuffer) {
  11. case compiler.MetaCommandSuccess:
  12. continue
  13. case compiler.MetaCommandUnrecognizedCommand:
  14. fmt.Printf("Unrecognized command %q \n", inputBuffer.Buffer)
  15. continue
  16. }
  17. }
  18. var statement compiler.Statement
  19. switch compiler.PrepareStatement(inputBuffer, &statement) {
  20. case compiler.PrepareSuccess:
  21. case compiler.PrepareUnrecognizedStatement:
  22. fmt.Printf("Unrecognized command at start of %q \n", inputBuffer.Buffer)
  23. continue
  24. case compiler.PrepareSyntaxError:
  25. fmt.Println("Syntax error. Could not parse statement.")
  26. continue
  27. }
  28. compiler.ExecuteStatement(statement)
  29. fmt.Println("Executed")
  30. }
  31. }
  32. func PrintPrompt() {
  33. fmt.Printf("db > ")
  34. }

Above is the code responsible for collecting user input etc.

  1. package compiler
  2. import (
  3. "bytes"
  4. "log"
  5. "os"
  6. "strconv"
  7. "strings"
  8. )
  9. type Row struct {
  10. ID int32
  11. Username string
  12. Email string
  13. }
  14. type Statement struct {
  15. RowToInsert Row
  16. Type StatementType
  17. }
  18. var (
  19. RowsTable = make([]Row, 0)
  20. RowsTableBuffer bytes.Buffer
  21. )
  22. func DoMetaCommand(buffer InputBuffer) MetaCommandResult {
  23. if buffer.Buffer == ".exit" {
  24. os.Exit(0)
  25. } else {
  26. return MetaCommandUnrecognizedCommand
  27. }
  28. return MetaCommandSuccess
  29. }
  30. func PrepareStatement(buffer InputBuffer, statement *Statement) PrepareResult {
  31. if len(buffer.Buffer) > 6 {
  32. bufferArguments := strings.Fields(buffer.Buffer)
  33. if bufferArguments[0] == "insert" {
  34. statement.Type = StatementInsert
  35. if len(bufferArguments) < 4 {
  36. return PrepareSyntaxError
  37. } else {
  38. i, err := strconv.Atoi(bufferArguments[1])
  39. if err != nil {
  40. log.Printf("%q is not a valid id\n", bufferArguments[1])
  41. return PrepareSyntaxError
  42. } else {
  43. statement.RowToInsert.ID = int32(i)
  44. }
  45. statement.RowToInsert.Username = bufferArguments[2]
  46. statement.RowToInsert.Email = bufferArguments[3]
  47. }
  48. RowsTable = append(RowsTable, statement.RowToInsert)
  49. return PrepareSuccess
  50. }
  51. }
  52. if buffer.Buffer == "select" {
  53. statement.Type = StatementSelect
  54. return PrepareSuccess
  55. }
  56. return PrepareUnrecognizedStatement
  57. }
  58. func ExecuteStatement(statement Statement) {
  59. switch statement.Type {
  60. case (StatementInsert):
  61. SerializeRow(RowsTable)
  62. case (StatementSelect):
  63. DeserializeRow()
  64. }
  65. }

The code above is for parsing and appending the entries into statements and depending on the keywords, it's either an insert or select [Took the code for defining enums out and left core logic]

  1. func SerializeRow(r []Row) {
  2. encoder := gob.NewEncoder(&RowsTableBuffer)
  3. err := encoder.Encode(r)
  4. if err != nil {
  5. log.Println("encode error:", err)
  6. }
  7. }
  8. func DeserializeRow() {
  9. var rowsBuffer = RowsTableBuffer
  10. rowsTable := make([]Row, 0)
  11. decoder := gob.NewDecoder(&rowsBuffer)
  12. err := decoder.Decode(&rowsTable)
  13. if err != nil {
  14. log.Println("decode error:", err)
  15. }
  16. fmt.Println(rowsTable)
  17. }

So the code above uses a global buffer in which the slice being appended to in PrepareStatement()will be encoded after an insert is done. A select ought to return the slice of all rows but just returns the first element for some reason.

Example (in terminal):
If I make 2 inserts:
db > insert 1 john c@mail.com
db > insert 2 collins k@mail.com

Then I make a select:
select
=> it returns [{1 john c@mail.com}] only.

Is there anything I am missing here? Thanks for your support.

答案1

得分: 0

所以答案很简单。我们在SerializeRow函数中创建了一个新的encoder,而不是只创建一次。我们将其从函数中提取出来,创建为全局变量。

  1. var (
  2. encoder = gob.NewEncoder(&RowsTableBuffer)
  3. decoder = gob.NewDecoder(&RowsTableBuffer)
  4. )
  5. func SerializeRow(r Row) {
  6. err := encoder.Encode(r)
  7. if err != nil {
  8. log.Println("encode error:", err)
  9. }
  10. }
  11. func DeserializeRow() {
  12. var rows Row
  13. err := decoder.Decode(&rows)
  14. for err == nil {
  15. if err != nil {
  16. log.Fatal("decode error:", err)
  17. }
  18. fmt.Printf("%d %s %s\n", rows.ID, rows.Username, rows.Email)
  19. err = decoder.Decode(&rows)
  20. }
  21. }
英文:

So the answer was pretty simple. We were creating a new encoder in the SerializeRow function instead of creating it once. We pulled it out of the function and created a global.

  1. var (
  2. encoder = gob.NewEncoder(&RowsTableBuffer)
  3. decoder = gob.NewDecoder(&RowsTableBuffer)
  4. )
  5. func SerializeRow(r Row) {
  6. err := encoder.Encode(r)
  7. if err != nil {
  8. log.Println("encode error:", err)
  9. }
  10. }
  11. func DeserializeRow() {
  12. var rows Row
  13. err := decoder.Decode(&rows)
  14. for err == nil {
  15. if err != nil {
  16. log.Fatal("decode error:", err)
  17. }
  18. fmt.Printf("%d %s %s\n", rows.ID, rows.Username, rows.Email)
  19. err = decoder.Decode(&rows)
  20. }
  21. }

huangapple
  • 本文由 发表于 2022年4月12日 06:36:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/71835056.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定