Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么json.Encoder会添加额外的一行?_Json_Go - Fatal编程技术网

为什么json.Encoder会添加额外的一行?

为什么json.Encoder会添加额外的一行?,json,go,Json,Go,似乎与json.marshall的行为稍有不同。具体来说,它在编码值的末尾添加一行新行。知道为什么吗?在我看来,它像一只虫子 package main import "fmt" import "encoding/json" import "bytes" func main() { var v string v = "hello" buf := bytes.NewBuffer(nil) json.NewEncoder(buf).Encode(v) b,

似乎与json.marshall的行为稍有不同。具体来说,它在编码值的末尾添加一行新行。知道为什么吗?在我看来,它像一只虫子

package main

import "fmt"
import "encoding/json"
import "bytes"

func main() {
    var v string
    v = "hello"
    buf := bytes.NewBuffer(nil)
    json.NewEncoder(buf).Encode(v)
    b, _ := json.Marshal(&v)

    fmt.Printf("%q, %q", buf.Bytes(), b)
}
这个输出

"\"hello\"\n", "\"hello\""

因为他们在使用
Encoder.Encode
时显式添加了一个新行字符。下面是该func的源代码,它实际上说明了它在文档中添加了一个换行符(请参见文档中的注释):

现在,除了“让输出看起来有点好”之外,Go开发人员为什么还要这么做呢?一个答案是:

流动 go json
编码器
针对流式传输进行了优化(例如,json数据的MB/GB/PB)。典型的情况是,当流媒体播放时,您需要一种在流媒体播放完成后进行清除的方法。对于
Encoder.Encode()
,这是一个
\n
换行符。当然,您当然可以写入缓冲区。但是您也可以写入io.Writer,它将流式传输
v

这与使用
json.Marshal
相反,如果您的输入来自不受信任(且未知有限)的源(例如,web服务的ajax POST方法-如果有人发布100MB json文件怎么办?),则通常不鼓励使用
json.Marshal。而且,
json.Marshal
将是json的最终完整集-例如,您不会期望将几个100个
Marshal
条目连接在一起。您可以使用Encoder.Encode()来构建一个大型集合,并写入缓冲区、流、文件、io.Writer等

每当我怀疑它是否是一个bug时,我总是查找源代码——这是一个优点,它的源代码和编译器就是纯粹的Go。在[n]vim中,我使用
\gb
在浏览器中打开源定义。

写入文档流。额外的空白终止流中的JSON文档


流读取器需要终止符。考虑包含这些JSON文档的流:<代码> 1 ,<代码> 2 ,<代码> 3 < /代码>。如果没有额外的空白,线路上的数据是字节序列
123
。这是一个编号为123的单一JSON文档,而不是三个文档。

您可以通过反向流重新生成换行符:

f, _ := os.OpenFile(fname, ...)
encoder := json.NewEncoder(f)
encoder.Encode(v)
f.Seek(-1, 1)
f.WriteString("other data ...")
他们应该让用户控制这种奇怪的行为:

  • 一个用于禁用它的生成选项
  • 编码器.SetEOF(eof字符串)
  • 编码器.SetIndent(前缀、缩进、eof字符串)

它使用换行符分隔多个对象。封送仅编码一个objectRight!这就是答案!它不使用它来分隔多个对象,因为您可以设置类似于
encoder.SetIndent(“,”)
的内容,然后您会得到到处都是的新行。分隔流的通常方法不是将
io.EOF
作为错误返回吗?使用
\n
在这里似乎没有什么用处。
io.EOF
通常表示所有数据的结束,即不会发送任何其他数据。但是,对于gzip编写器来说,情况并非如此;无论何时刷新,它都会发送io.EOF。即使通过刷新,您仍然可以继续读取gzip流。
f, _ := os.OpenFile(fname, ...)
encoder := json.NewEncoder(f)
encoder.Encode(v)
f.Seek(-1, 1)
f.WriteString("other data ...")