If I understood it right, *s = *(*State)(&state) copies the content at &state to the s address (after casting *rawState to *State). But if it is that way, wouldn't it be more efficient to just do s = (*State)(&state) instead of copying and *state being collected by GC? Or could it lead to side-effects changing the value of s / or other reasons for doing it this way? Thanks!
complete function from [0]:
func (s *State) UnmarshalJSON(b []byte) error {
type rawState State
var state rawState
dec := json.NewDecoder(bytes.NewReader(b))
if s.useJSONNumber {
dec.UseNumber()
}
err := dec.Decode(&state)
if err != nil {
return err
}
*s = *(*State)(&state)
return s.Validate()}
CodePudding user response:
The assignment:
*s = *(*State)(&state)
Does copy the pointed value. This is required because s is a local variable, assigning anything to s itself will have no effect once the function returns.
The intention is to assign something where s points to, and that is what the above assignment statement does.
The goal of using rawState is to create a new type which does not have the UnmarshalJSON() method, so passing *rawState to json.Unmarshal() will not cause a stack overflow.
See related: Call json.Unmarshal inside UnmarshalJSON function without causing stack overflow
CodePudding user response:
s is a pointer lets say pointing to location x in memory.
&state is another pointer at memory location y.
the function UnmarshalJSON is called with pointer pointing to memory location x.
if you do:
*s = *(*State)(&state)
this means:
take pointer to y(&state), convert it to the correct pointer type(*State), then go to memory location y(* at the beginning after =) and then copy the value(=), to this other memory location x(*s).
if you, on the other hand, do: s = (*State)(&state)
this means:
take pointer to y(&state), convert it to correct pointer type(*State), copy that pointer(=) to receiver (s). The memory location x being pointed to by whatever called this function, remains unchanged.
Also when the method is called the pointer itself, received by UnmarshalJSON as s, is a copy of the pointer at the position it's called from. This s inside UnmarshalJSON is a value of type *State that does not exist beyond UnmarshalJSON. This assignment will hence be meaningless beyond UnmarshalJSON.
