我想做什么?
复制"默认"在需要时构建一个新的,保留所有值。
详情
我正在尝试复制Chat
结构:
type ChatData struct {
User map[string]map[string]string `json:"user"`
Chat map[string]string `json:"chat"`
}
type Chat struct {
Settings map[string]map[string]interface{} `json:"settings"`
Data ChatData `json:"data"`
}
我只需要在引入新聊天时执行此操作,并检查map[string]Chat
中的成员资格。
//data is a map[string]Chat
if _, exists := data[event.Chat]; !exists {
data[event.Chat] = data["default"]
}
完整的默认结构是:
{
"default": {
"settings": {
"eightball": {
"messages": [
"yes",
"no",
"maybe"
]
},
"main": {
"blacklistedCommands": [],
"blacklistedUsers": [],
"error": "there was an error - ",
"maxConsecutive": 5,
"permissions": "You don't have permissions for that command.",
"success": "The command was successful.",
"whitelistedCommands": [],
"whitelistedUsers": []
}
},
"data": {
"user": {
"default": {
"admin": "false",
"consecutiveCommands": "0",
"nickname": "",
"sentMessages": "0"
},
"total": {
"admin": "false",
"consecutiveCommands": "0",
"nickname": "",
"sentMessages": "0"
}
},
"chat": {
"commandSender": "",
"lastMessage": "",
"lastSender": "",
"lastTimestamp": "",
"wasCommand":""
}
}
}
}
我尝试了什么
data[event.Chat] = data["default"]
// causes a reference
data[event.Chat] = &data["default"]
// cannot use &data["default"] (type *Chat) as type Chat in assignment
data[event.Chat] = *data["default"]
// invalid indirect of data["default"] (type Chat)
我是否需要将map[string]Chat
的使用更改为map[string]*Chat
并使用第二个选项?指针和参考文献不是我的专长,所以请帮助。
修改
谁认为我在复制地图,你在吸什么?
答案 0 :(得分:2)
我在之前的案例中发现,复制复杂结构的一种简单(虽然不是最有效)的方法是对其进行Marshal,然后将其解组为一个新变量。这可以通过各种编码来完成。两个简单的(包括在stdlib中)将是json和gob。
还有很多图书馆使用反射来实现类似的目标:https://github.com/jinzhu/copier
但就像我说的那样,虽然效率不高,但这很容易理解,只需要一个简单的功能即可实现。如果表现很重要,你应该选择gob而不是json。如果性能真的很重要,那么你应该更喜欢另一种解决方案。
答案 1 :(得分:1)
如果您了解数据结构,则最好完全定义结构。它比复杂的地图和具有反射的界面更易于管理数据类型。这是一个帮助您将JSON转换为Go结构的工具。它并不完美,您必须确认数据类型。您甚至可能想要删除内部结构并为它们创建类型以便于阅读和维护,但它会为您节省一些时间。
https://mholt.github.io/json-to-go/
package main
import (
"encoding/json"
"fmt"
"log"
)
var rawDataExample = []byte(`{
"default": {
"settings": {
"eightball": {
"messages": [
"yes",
"no",
"maybe"
]
},
"main": {
"blacklistedCommands": [],
"blacklistedUsers": [],
"error": "there was an error - ",
"maxConsecutive": 5,
"permissions": "You don't have permissions for that command.",
"success": "The command was successful.",
"whitelistedCommands": [],
"whitelistedUsers": []
}
},
"data": {
"user": {
"default": {
"admin": "false",
"consecutiveCommands": "0",
"nickname": "",
"sentMessages": "0"
},
"total": {
"admin": "false",
"consecutiveCommands": "0",
"nickname": "",
"sentMessages": "0"
}
},
"chat": {
"commandSender": "",
"lastMessage": "",
"lastSender": "",
"lastTimestamp": "",
"wasCommand":""
}
}
}
}
`)
type Settings struct {
Default struct {
Settings struct {
Eightball struct {
Messages []string `json:"messages"`
} `json:"eightball"`
Main struct {
BlacklistedCommands []string `json:"blacklistedCommands"`
BlacklistedUsers []string `json:"blacklistedUsers"`
Error string `json:"error"`
MaxConsecutive int `json:"maxConsecutive"`
Permissions string `json:"permissions"`
Success string `json:"success"`
WhitelistedCommands []string `json:"whitelistedCommands"`
WhitelistedUsers []string `json:"whitelistedUsers"`
} `json:"main"`
} `json:"settings"`
Data struct {
User struct {
Default struct {
Admin string `json:"admin"`
ConsecutiveCommands string `json:"consecutiveCommands"`
Nickname string `json:"nickname"`
SentMessages string `json:"sentMessages"`
} `json:"default"`
Total struct {
Admin string `json:"admin"`
ConsecutiveCommands string `json:"consecutiveCommands"`
Nickname string `json:"nickname"`
SentMessages string `json:"sentMessages"`
} `json:"total"`
} `json:"user"`
Chat struct {
CommandSender string `json:"commandSender"`
LastMessage string `json:"lastMessage"`
LastSender string `json:"lastSender"`
LastTimestamp string `json:"lastTimestamp"`
WasCommand string `json:"wasCommand"`
} `json:"chat"`
} `json:"data"`
} `json:"default"`
}
type Data struct {
Events map[string]Settings
}
func main() {
var settings Settings
err := json.Unmarshal(rawDataExample, &settings)
if err != nil {
log.Fatal(err)
}
event := "foo"
d := Data{
Events: make(map[string]Settings),
}
if _, ok := d.Events[event]; !ok {
// event doesn't exist
// add it
d.Events[event] = settings
fmt.Println("event added")
}
if _, ok := d.Events[event]; !ok {
// event exist, this will never be happen
// sanity check
fmt.Println("this will never be printed")
}
fmt.Printf("%+v\n", d)
}
答案 2 :(得分:-1)
超级简单的修复,只是想在我做之前得到一些输入。更改了map[string]Chat
> map[string]*Chat
并制作了新的*Chat
,然后复制了数据。
data[event.Chat] = &Chat{}
*data[event.Chat] = *data["default"]