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
.