由于任何有效值
string都是有效键,而且也是JSON中的有效值(有关详细信息,请参阅JSON键名中的哪些字符有效/无效?,因此从理论上讲,它不会返回任何错误。
如果发生内存不足错误,则
json.Marshal()不会返回错误,您的应用将终止并显示错误代码。
由于Go将
string值存储为其UTF-8编码的字节序列,因此存在无效的UTF-8编码的字符串内容的问题。这也不会导致任何错误,因为Go会将无效的代码点替换为Unipre替换字符U+ FFFD,例如以下示例:
m := map[string]string{"xff": "a"}data, err := json.Marshal(m)fmt.Println(string(data), err)输出(在Go Playground上尝试):
{"ufffd":"a"} <nil>此行为记录在
json.Marshal():
字符串值编码为强制转换为有效UTF-8的JSON字符串,用Unipre替换符文替换无效字节。
封送a
map[string]string可能永远不会返回错误,但是,除非文档明确指出返回
error的总是
nil(除非doc
json.Marshal()并未记录这种行为),否则应始终检查返回的错误。这种罕见的例子是
rand.Read()哪个文档_“总是返回len(p)和nil错误”_ 。
而且标准库也有可能存在错误,因此,即使
json封包的实现可能在封送a时不 打算
返回任何错误
map[string]string,但错误可能会导致它仍然返回非
nil错误。
并发地图修改
为了完整起见,让我们讨论
json.Marshal()将a
map[string]string传递给它时可能导致失败的另一个问题。
Go
1.6向运行时添加了轻量级的并发滥用映射检测功能
这意味着Go运行时可以检测是否在goroutine中读取或修改了映射,并且还同时由另一个goroutine修改了该映射,而无需同步。
因此,这里的情况是我们将传递
map[string]string给
json.Marshal()。而要使其封送,该
json程序包显然必须遍历地图的键值。如果我们同时修改地图,将导致失败。
这是激发它的示例代码(存在循环以增加并发修改的可能性,否则我们将由goroutine调度程序处理):
m := map[string]string{"xff": "a"}go func() { for i := 0; i < 10000; i++ { m["x"] = "b" }}()for i := 0; i < 10000; i++ { if _, err := json.Marshal(m); err != nil { panic(err) }}还要注意,在这种情况下
json.Marshal()也不会返回(就像发生内存不足错误一样),而是运行时将有意使您的应用程序崩溃。输出将是:
fatal error: concurrent map iteration and map write


![可以将map [string] string编组到json会返回错误吗? 可以将map [string] string编组到json会返回错误吗?](http://www.mshxw.com/aiimages/31/633158.png)
