英文:
Copying pointer content in go causing uneccesary overhead?
问题
如果我理解正确的话,*s = *(*State)(&state) 将 &state 处的内容复制到了 s 的地址上(在将 *rawState 强制转换为 *State 之后)。但如果是这样的话,直接执行 s = (*State)(&state) 不是更高效吗?这样就不需要复制,而且 *state 也不会被垃圾回收。或者这种方式可能会导致副作用,改变 s 的值或者其他原因导致这样做吗?谢谢!
完整的函数代码如下:
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()
}
英文:
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()}
答案1
得分: 1
这个任务:
*s = *(*State)(&state)
确实复制了指向的值。这是必需的,因为s是一个局部变量,将任何东西赋给s本身在函数返回后将没有任何效果。
这个语句的意图是将某个东西赋给s指向的位置,这就是上面的赋值语句所做的事情。
使用rawState的目的是创建一个没有UnmarshalJSON()方法的新类型,因此将*rawState传递给json.Unmarshal()不会导致堆栈溢出。
参考链接:https://stackoverflow.com/questions/43176625/call-json-unmarshal-inside-unmarshaljson-function-without-causing-stack-overflow/43178272#43178272
英文:
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.
答案2
得分: 0
s是一个指针,假设指向内存中的位置x。
&state是另一个指针,指向内存位置y。
函数UnmarshalJSON被调用时,使用指向内存位置x的指针。
如果你执行以下操作:
*s = *(*State)(&state)
这意味着:
取指向y(&state)的指针,将其转换为正确的指针类型(*State),然后转到内存位置y(在=之后的*),然后将该值(=)复制到另一个内存位置x(*s)。
另一方面,如果你执行:s = (*State)(&state)
这意味着:
取指向y(&state)的指针,将其转换为正确的指针类型(*State),将该指针(=)复制给接收器(s)。调用此函数的任何位置指向的内存位置x保持不变。
此外,当方法被调用时,指针本身作为s传递给UnmarshalJSON,它是从调用它的位置复制的指针。UnmarshalJSON内部的s是类型为*State的值,它在UnmarshalJSON之外不存在。因此,这个赋值在UnmarshalJSON之外是没有意义的。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论