英文:
Why json.Marshal and json.Unmarshal have different signature
问题
func Marshal(v interface{}) ([]byte, error)
func Unmarshal(data []byte, v interface{}) error
请注意,Marshal函数接受一个接口作为输入,并返回一个[]byte作为输出,而Unmarshal函数接受一个[]byte作为输入,并直接将输出写入到输入参数data中。
这两者在设计上有何区别呢?
一个相关的问题:
我认为使用输入参数可以节省内存拷贝(函数返回需要一次拷贝),在Go语言中,每次赋值都是一次拷贝操作,所以看起来Unmarshal可以节省一次拷贝,但Marshal不行。
所以我感到困惑...
英文:
func Marshal(v interface{}) ([]byte, error)
func Unmarshal(data []byte, v interface{}) error
notice that Marshal accept an interface and return a []byte as output, while Unmarshal accept an []byte and write output directly to the input parameter data
what make the difference in design
an associate question:
I think use input parameter could save in-memory copy once(function return need a copy), every assignment in golang is a copy op, so it looks like Unmarshal can save a copy, but Marshal not.
so I'm confused...
答案1
得分: 3
对称对中的潜在函数如下:
func Marshal(v interface{}) ([]byte, error) // 1
func Unmarshal(data []byte) (interface{}, error) // 2
func Marshal(v interface{}, data *[]byte) error // 3
func Unmarshal(data []byte, v interface{}) error // 4
函数 #3 和 #4 看起来可能不对称,因为 #3 的 data
参数是指针类型,而 #4 的 v
参数没有声明为指针类型。实际上它们是对称的,因为传递给 #4 的 v
参数的实际值必须是指针。如果它不是指针,则函数返回错误。
函数 #2 不可行,因为该函数无法访问应用程序的结果类型。如果函数不知道类型,它无法将 JSON 反序列化为该类型。此外,应用程序需要进行类型断言才能使用结果。标准库在可能的情况下避免使用类型断言。
函数 #3 不符合惯用写法。在 Go 中很少使用指向切片的指针。我不记得标准库中有任何使用它的情况,但如果有的话,我相信有人会在这里留下评论。
我们只剩下不对称的 #1 和 #4:
func Marshal(v interface{}) ([]byte, error) // 1
func Unmarshal(data []byte, interface{}) error // 4
英文:
The potential functions in symmetric pairs are:
func Marshal(v interface{}) ([]byte, error) // 1
func Unmarshal(data []byte) (interface{}, error) // 2
func Marshal(v interface{}, data *[]byte) error // 3
func Unmarshal(data []byte, v interface{}) error // 4
Functions #3 and #4 might not look symmetric because the data
argument to #3 is a pointer type and the v
argument to #4 is not declared to be a pointer type. They are in fact symmetric because the actual value passed to the v
argument of #4 must be a pointer. The function returns an error if it is not a pointer.
Function #2 is not viable because the function does not have access to the application's result type. The function cannot unmarshal the JSON to a type if the type is not known to the function. Further, the application will need to type assert the result to use it. The standard library avoids type assertions when possible.
Function #3 is not idiomatic. Pointers to slices are rarely used in Go. I don't recall the use of any in the standard library, but I am sure someone will leave a comment here if there is a one.
We are left with the unsymmetric pair of #1 and #4:
func Marshal(v interface{}) ([]byte, error) // 1
func Unmarshal(data []byte, interface{}) error // 4
答案2
得分: 0
通过让Marshal
返回一个字节数组,你可以轻松地将其传递给像bufio.Writer.Write()
这样的函数,该函数以字节数组作为参数。当你编写一个提供JSON的Web服务时,可能会用到这样的函数。
如果你正在使用Unmarshal
,那么你可能正在从JSON中读取数据。通过让Unmarshal
接受与Marshal
返回值相同的第一个参数,你可以获取Marshal
输出的任何JSON,并直接将其传递给Unmarshal
。
英文:
By having Marshal
return a byte array, you can easily pass that to functions like bufio.Writer.Write()
which takes a byte array as an argument. You might have one of those when you're writing a web service that serves JSON.
If you're using Unmarshal
, then you're likely reading from JSON. By having Unmarshal
take the same first argument as Marshal
returns, you can get any JSON that has been output by Marshal
, and pass it straight to Unmarshal
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论