doushao1087 2018-03-07 16:47
浏览 43
已采纳

函数参数是接口时将复制什么

Assumptions: In go, all function arguments are passed by value. To get pass-by-reference semantics/performance, go programmers pass values by pointer. Go will still make a copy of these arguments, but its making a copy of a pointer which is sometimes more memory efficient than making a copy of the actual parameter.

Question: What is going on when you pass an interface? i.e., in a program like this

package main
import "fmt"

type Messages struct {
    hello string
}

func main() {
  sayHelloOne(Messages{"hello world"});
  sayHelloTwo(&Messages{"hello world"});
  sayHelloThree(Messages{"hello world"});
}


//go makes a copy of the struct
func sayHelloOne(messages Messages) {
  fmt.Println(messages.hello)
}

//go makes a *pointer* to the struct
func sayHelloTwo(messages *Messages) {
  fmt.Println(messages.hello)
}

//go --- ???
func sayHelloThree(messages interface{}) {
  fmt.Println(messages.(Messages).hello)
}

What happens with the argument when a programmer calls the sayHelloThree function? Is messages being copied? Or is it a pointer to messages that's copied? Or is there some weird-to-me deferring going on until messages is cast?

  • 写回答

1条回答 默认 最新

  • douyan1944 2018-03-07 17:02
    关注

    The interface value is copied. The interface value includes an underlying type descriptor and the underlying value, which may be any type (pointer or otherwise) which satisfies the interface. Being "wrapped" in an interface has no impact on these semantics. You can see this in your own quoted code: you have to assert the type to a Messages value, not a *Messages pointer. If, on the other hand, you passed a *Messages in as the parameter, that's what you'd get inside the function.

    This is easily demonstrated experimentally:

    m := Messages{"hello world"}
    var mi interface{}
    mi = m
    m.hello = "wait what?"
    fmt.Println(mi.(Messages).hello)
    // hello world
    

    Working playground example: https://play.golang.org/p/lnVzr79eUZF

    Also, be careful with generalizations like "making a copy of a pointer which is much more memory efficient than making a copy of the actual parameter" - this is not universally true, and the change in semantics is often more important than the change in resource usage patterns. For example, a pointer is obviously less efficient when the value is smaller than an address on the operating architecture. A pointer can also force the value onto the heap rather than the stack, which - regardless of its impact on memory usage - increases GC pressure, because the GC gets to ignore values on the stack.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog