假设:在go中,所有函数参数都按值传递。要获得pass-by-reference语义/性能,请让程序员通过指针传递值。 Go仍然会复制这些参数,但它会制作一个指针的副本,这个指针有时比制作实际参数的副本更有效。
问题:通过界面时发生了什么?即,在像这样的程序中
def reverse(sentence):
answer = ''
temp = ''
for char in sentence:
if char != ' ':
temp += char
continue
rev = ''
for i in range(len(temp)):
rev += temp[len(temp)-i-1]
answer += rev + ' '
temp = ''
return answer + temp
reverse("This is a string to try")
当程序员调用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)
}
函数时,参数会发生什么? sayHelloThree
被复制了吗?或者它是指向messages
复制的指针?或者在推出messages
之前是否有一些奇怪的推迟?
答案 0 :(得分:3)
复制接口值。接口值包括底层类型描述符和底层值,它可以是满足接口的任何类型(指针或其他)。被包裹"在接口中对这些语义没有影响。您可以在自己的引用代码中看到这一点:您必须将类型断言为Messages
值,而不是*Messages
指针。另一方面,如果您通过了*Messages
作为参数,那就是您在函数中获得的内容。
这很容易通过实验证明:
m := Messages{"hello world"}
var mi interface{}
mi = m
m.hello = "wait what?"
fmt.Println(mi.(Messages).hello)
// hello world
工作场所示例:https://play.golang.org/p/lnVzr79eUZF
另外,要小心像&#34这样的概括;制作一个指针的副本,它比制作实际参数的副本更具记忆效率。 - 这并非普遍适用,语义的变化通常比资源使用模式的变化更重要。例如,当值小于操作体系结构上的地址时,指针显然效率较低。指针也可以强制将值强加到堆而不是堆栈,无论它对内存使用的影响如何,都会增加GC压力,因为GC会忽略堆栈上的值。