在外部函数中从Bolt数据库反序列化JSON时,出现了意外的故障地址错误。

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

Getting unexpected fault address error when unmarshalling json from bolt database in external function

问题

我目前正在处理在Go语言中从Bolt数据库中存储/检索字符的问题。我编写了以下函数来检索存储的每个字符,它运行良好。

// 这个函数运行良好
func GetAllCharacters() []Character {
	var charList []Character
	var char Character

	db, err := bolt.Open("./savedata/database.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	err = db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket([]byte("DB")).Bucket([]byte("Characters")).Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			err := json.Unmarshal(v, &char)
			if err != nil {
				log.Fatal(err)
			}
			charList = append(charList, char)
		}

		return nil
	})

	if err != nil {
		log.Fatal(err)
	}

	return charList
}

然后,我想整理一下代码,将函数的一部分移到另一个文件中,像这样:

utils文件:

package utils

func GetAllCharactersFromDB() [][]byte {
	var charList [][]byte

	db, err := bolt.Open("./savedata/database.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	err = db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket([]byte("DB")).Bucket([]byte("Characters")).Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			charList = append(charList, v)
		}

		return nil
	})

	if err != nil {
		log.Fatal(err)
	}

	return charList
}

main文件:

func GetAllCharacters() []Character {
	var charList []Character
	var char Character

	allChars := utils.GetAllCharactersFromDB()

	for _, v := range allChars {
		err := json.Unmarshal(v, &char)
		if err != nil {
			log.Fatal(err)
		}
		charList = append(charList, char)
	}

	return charList
}

现在,当我尝试运行这段代码时,我得到了一个我无法理解的加密错误消息:

unexpected fault address 0x20d5607405f
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0x20d5607405f pc=0xa4ba35]

goroutine 1 [running]:
runtime.throw({0xa93ef9, 0x20d30d50108})
        C:/Program Files/Go/src/runtime/panic.go:1198 +0x76 fp=0xc0001096a0 sp=0xc000109670 pc=0x9b4b16
runtime.sigpanic()
        C:/Program Files/Go/src/runtime/signal_windows.go:260 +0x10c fp=0xc0001096e8 sp=0xc0001096a0 pc=0x9c606c
encoding/json.checkValid({0x20d5607405f, 0x27a, 0x1}, 0xc00011c0b8)
        C:/Program Files/Go/src/encoding/json/scanner.go:32 +0xb5 fp=0xc000109710 sp=0xc0001096e8 pc=0xa4ba35
encoding/json.Unmarshal({0x20d5607405f, 0xac2ec0, 0xc000006010}, {0xa8b400, 0xc000118120})
        C:/Program Files/Go/src/encoding/json/decode.go:101 +0x5a fp=0xc000109758 sp=0xc000109710 pc=0xa3cc9a
github.com/my_name/gotestgame/game.GetAllCharacters()
        C:/Users/my_name/Documents/Golang/simplegame/game/characters.go:164 +0xcc fp=0xc000109808 sp=0xc000109758 pc=0xa63b4c
github.com/my_name/gotestgame/game.Leaderboard()
        C:/Users/my_name/Documents/Golang/simplegame/game/level.go:125 +0xab fp=0xc000109d20 sp=0xc000109808 pc=0xa6782b
github.com/my_name/gotestgame/game.MainMenu()
        C:/Users/my_name/Documents/Golang/simplegame/game/menu.go:58 +0x3ba fp=0xc000109f60 sp=0xc000109d20 pc=0xa699da
main.main()
        C:/Users/my_name/Documents/Golang/simplegame/main.go:16 +0x4a fp=0xc000109f80 sp=0xc000109f60 pc=0xa6d4ea
runtime.main()
        C:/Program Files/Go/src/runtime/proc.go:255 +0x217 fp=0xc000109fe0 sp=0xc000109f80 pc=0x9b70d7
runtime.goexit()
        C:/Program Files/Go/src/runtime/asm_amd64.s:1581 +0x1 fp=0xc000109fe8 sp=0xc000109fe0 pc=0x9df7e1
exit status 2

有人能告诉我为什么新的方法不起作用吗?我该怎么做才能让它工作?我认为json.Unmarshal在两种情况下都会解组相同的[]byte,我错了吗?当我在GetAllCharactersFromDB()函数中打印string(v)的内容时,我得到了一个可读的JSON字符串。虽然第一个代码片段可以工作,但我困扰于无法弄清楚为什么第二种方法不起作用。对不起,如果这是一个愚蠢的问题,我对Go语言还不太熟悉。

编辑:

回应评论,这是一个Character的样子:

type Character struct {
	Name         string `json:"name"`
	Hardcore     bool   `json:"hardcore"`
	Default      bool   `json:"default"`
	Level        int    `json:"level"`
	XP           int    `json:"xp"`
	Class        string `json:"class"`
	Max_HP       int    `json:"max_hp"`
	Current_HP   int    `json:"current_hp"`
	Strength     int    `json:"str"`
	Dexterity    int    `json:"dex"`
	Intelligence int    `json:"int"`
	Gold         int    `json:"gold"`
	Weapon       Weapon `json:"weapon"`
	Items        []Item `json:"items"`
}

这是存储的数据的样子:

{"name":"Test1","hardcore":true,"default":true,"level":1,"xp":1,"class":"Barbarian","max_hp":150,"current_hp":150,"str":30,"dex":15,"int":5,"gold":0,"weapon":{"Name":"Rusty Club","Description":"Starter Weapon for the Barbarian.","Rarity":{"Common":1,"Uncommon":0,"Rare":0,"Epic":0,"Legendary":0},"LowAttack":15,"HighAttack":40,"AttackSpeed":1.2,"CritChance":5,"Accuracy":95,"Range":10,"ReqStr":15,"ReqDex":5,"ReqInt":0,"BuyPrice":30,"SellPrice":1},"items":[{"Name":"Small Healing Potion","Description":"Heals you for 20 HP","Tag":"Heal","Rarity":{"Common":1,"Uncommon":0,"Rare":0,"Epic":0,"Legendary":0},"BuyPrice":25,"SellPrice":1}]}
英文:

I am currently working on storing/retrieving characters from a Bolt Database in Go.
I wrote this function here to retrieve every character stored and it worked fine.

//this works fine
func GetAllCharacters() []Character {
	var charList []Character
	var char Character

	db, err := bolt.Open("./savedata/database.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
    defer db.Close()

	err = db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket([]byte("DB")).Bucket([]byte("Characters")).Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			err := json.Unmarshal(v, &char)
			if err != nil {
				log.Fatal(err)
			}
			charList = append(charList, char)
		}

		return nil
	})

	if err != nil {
		log.Fatal(err)
	}

	return charList
}

Then I wanted to clean up my code a bit and moved a part of the function to a different file, like this:

utils file:

package utils

func GetAllCharactersFromDB() [][]byte {
	var charList [][]byte

	db, err := bolt.Open("./savedata/database.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
    defer db.Close()

	err = db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket([]byte("DB")).Bucket([]byte("Characters")).Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			charList = append(charList, v)
		}

		return nil
	})

	if err != nil {
		log.Fatal(err)
	}

	return charList
}

main file:

func GetAllCharacters() []Character {
	var charList []Character
	var char Character

	allChars := utils.GetAllCharactersFromDB()

	for _, v := range allChars {
		err := json.Unmarshal(v, &char)
		if err != nil {
			log.Fatal(err)
		}
		charList = append(charList, char)
	}

	return charList
}

And now when I try to run this code, I get a this cryptic error message that I cannot really decrypt:

unexpected fault address 0x20d5607405f
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0x20d5607405f pc=0xa4ba35]

goroutine 1 [running]:
runtime.throw({0xa93ef9, 0x20d30d50108})
        C:/Program Files/Go/src/runtime/panic.go:1198 +0x76 fp=0xc0001096a0 sp=0xc000109670 pc=0x9b4b16
runtime.sigpanic()
        C:/Program Files/Go/src/runtime/signal_windows.go:260 +0x10c fp=0xc0001096e8 sp=0xc0001096a0 pc=0x9c606c
encoding/json.checkValid({0x20d5607405f, 0x27a, 0x1}, 0xc00011c0b8)
        C:/Program Files/Go/src/encoding/json/scanner.go:32 +0xb5 fp=0xc000109710 sp=0xc0001096e8 pc=0xa4ba35
encoding/json.Unmarshal({0x20d5607405f, 0xac2ec0, 0xc000006010}, {0xa8b400, 0xc000118120})
        C:/Program Files/Go/src/encoding/json/decode.go:101 +0x5a fp=0xc000109758 sp=0xc000109710 pc=0xa3cc9a
github.com/my_name/gotestgame/game.GetAllCharacters()
        C:/Users/my_name/Documents/Golang/simplegame/game/characters.go:164 +0xcc fp=0xc000109808 sp=0xc000109758 pc=0xa63b4c
github.com/my_name/gotestgame/game.Leaderboard()
        C:/Users/my_name/Documents/Golang/simplegame/game/level.go:125 +0xab fp=0xc000109d20 sp=0xc000109808 pc=0xa6782b
github.com/my_name/gotestgame/game.MainMenu()
        C:/Users/my_name/Documents/Golang/simplegame/game/menu.go:58 +0x3ba fp=0xc000109f60 sp=0xc000109d20 pc=0xa699da
main.main()
        C:/Users/my_name/Documents/Golang/simplegame/main.go:16 +0x4a fp=0xc000109f80 sp=0xc000109f60 pc=0xa6d4ea
runtime.main()
        C:/Program Files/Go/src/runtime/proc.go:255 +0x217 fp=0xc000109fe0 sp=0xc000109f80 pc=0x9b70d7
runtime.goexit()
        C:/Program Files/Go/src/runtime/asm_amd64.s:1581 +0x1 fp=0xc000109fe8 sp=0xc000109fe0 pc=0x9df7e1
exit status 2

Can anyone tell me why the new approach does not work? And what I could do to make it work? I thought the json.Unmarshal would be unmarshalling the same []byte in both cases, or am I wrong there? When I print out the content of string(v) in the GetAllCharactersFromDB() function I get a readable json string. It is not very urgent as the first code snippet works, but it bothers me that I cannot figure out why the second approach does not work. Sorry if this is a stupid question, I am fairly new to Go.

EDIT:

In response to the comment, heres how a Character looks:

type Character struct {
	Name         string `json:"name"`
	Hardcore     bool   `json:"hardcore"`
	Default      bool   `json:"default"`
	Level        int    `json:"level"`
	XP           int    `json:"xp"`
	Class        string `json:"class"`
	Max_HP       int    `json:"max_hp"`
	Current_HP   int    `json:"current_hp"`
	Strength     int    `json:"str"`
	Dexterity    int    `json:"dex"`
	Intelligence int    `json:"int"`
	Gold         int    `json:"gold"`
	Weapon       Weapon `json:"weapon"`
	Items        []Item `json:"items"`
}

And here's how the data stored looks:

{"name":"Test1","hardcore":true,"default":true,"level":1,"xp":1,"class":"Barbarian","max_hp":150,"current_hp":150,"str":30,"dex":15,"int":5,"gold":0,"weapon":{"Name":"Rusty Club","Description":"Starter Weapon for the Barbarian.","Rarity":{"Common":1,"Uncommon":0,"Rare":0,"Epic":0,"Legendary":0},"LowAttack":15,"HighAttack":40,"AttackSpeed":1.2,"CritChance":5,"Accuracy":95,"Range":10,"ReqStr":15,"ReqDex":5,"ReqInt":0,"BuyPrice":30,"SellPrice":1},"items":[{"Name":"Small Healing Potion","Description":"Heals you for 20 HP","Tag":"Heal","Rarity":{"Common":1,"Uncommon":0,"Rare":0,"Epic":0,"Legendary":0},"BuyPrice":25,"SellPrice":1}]}

答案1

得分: 2

请尝试将以下行替换为:

charList = append(charList, v)

替换为

vc := make([]byte, len(v))
copy(vc,v)
charList = append(charList, vc)
英文:

Please try to replace the following line:

charList = append(charList, v)

with

vc := make([]byte, len(v))
copy(vc,v)
charList = append(charList, vc)

huangapple
  • 本文由 发表于 2022年1月4日 22:29:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/70580331.html
匿名

发表评论

匿名网友

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

确定