在Go语言中复制指针内容是否会导致不必要的开销?

huangapple go评论70阅读模式
英文:

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()
}

[0] https://github.com/hashicorp/terraform-json/blob/d1018bf93fd9c097133b0159ab8b3c0517a846c9/state.go#L73

英文:

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()}

[0] https://github.com/hashicorp/terraform-json/blob/d1018bf93fd9c097133b0159ab8b3c0517a846c9/state.go#L73

答案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.

See related: https://stackoverflow.com/questions/43176625/call-json-unmarshal-inside-unmarshaljson-function-without-causing-stack-overflow/43178272#43178272

答案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.

huangapple
  • 本文由 发表于 2021年10月5日 18:01:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/69448457.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定