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