gob 解码器 returns 仅数组中的第一个元素
gob decoder returns only first element in the array
所以我试图创建一个模拟数据库,在当前的实现中,我试图制作一个 insert
和 select
插入行和 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()
}
}
上面的代码用于解析条目并将其附加到语句中,根据关键字,它可以是 insert
或 select
[取出用于定义枚举的代码并保留核心逻辑]
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)
}
}
所以我试图创建一个模拟数据库,在当前的实现中,我试图制作一个 insert
和 select
插入行和 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()
}
}
上面的代码用于解析条目并将其附加到语句中,根据关键字,它可以是 insert
或 select
[取出用于定义枚举的代码并保留核心逻辑]
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)
}
}