我有以下功能:

其中Set(treats的类型)是具有以下定义的接口:

题:

mtreatsdog是通过引用传递的,并且meowId是否已复制其值?

我认为:

  • m是引用传递的,因为它是一个映射
  • dog是一个结构。 因此,我应该传递指针以避免复制数据

接口类型只是一组方法。请注意,接口定义的成员未指定接收方类型是否为指针。这是因为值类型的方法集是其关联的指针类型的方法集的子集。满嘴我的意思是,如果您具有以下条件:

然后定义以下两种方法:

然后,类型Whatever仅具有方法Bar(),而类型*Whatever具有方法Foo()Bar()。这意味着如果您具有以下界面:

然后*Whatever实现了Grits,而Whatever没有实现,因为Whatever缺少方法Foo()。当您将函数的输入定义为接口类型时,您不知道它是指针还是值类型。

下面的示例说明了一种采用两种方式都采用接口类型的函数:

您可以调用Raname(&f,"Jorelli Fruit")而不是Rename(c,"Jorelli Bar"),因为Fruit*Fruit都实现了Renamable,而实现了RenableCandy却没有。

http://play.golang.org/p/Fb-L8Bvuwj


引用传递是一种语言,Go中没有什么是"引用传递"。通过引用传递意味着赋值运算符可以在单独使用时更改原始值。但是,有些引用类型(例如映射和指针)指向某处。除非您使用其他操作符,例如地图索引和*操作符,否则在它们上使用赋值操作符将不会修改原始操作符。

您正确的认为映射m是引用类型,因此就像指针一样。除了替换地图以外,对地图的任何更改都会修改原始地图。

如果存在真实的"通过引用传递",第二个示例将修改原始地图。

与使用dog一样,传递指针可让您修改原始指针。如果调用任何指针方法或使用*运算符,则原始格式将更改。在您的示例中,可能不需要指针。如果dog很小,则传递副本可能会更容易。由程序员决定何时是使用指针的好时机。

Set未通过引用传递。接口不是参考。虽然在6g编译器内部确实有一个接口使用了指针,但该接口本身却不像指针。不管接口包含的对象大小如何,传递接口与使用6g编译器传递指针一样便宜。但是,没有办法像使用指针和映射那样修改接口的原始值。

尽管您不能修改传递的原始接口,但该接口可以包含指针类型。在这种情况下,它的作用就像狗指针,其中某些方法的调用可以修改原始方法。对于您的特定Set接口,我想它包含基于方法名称的指针类型。因此,当您调用set.Add(whatever)时,它将更改原始文件的内部数据。


Calls, The Go Programming Language Specification

In a function call, the function value and arguments are evaluated in
the usual order. After they are evaluated, the parameters of the call
are passed by value to the function and the called function begins
execution. The return parameters of the function are passed by value
back to the calling function when the function returns.

When are function parameters passed by value? FAQ - The Go
Programming Language.

As in all languages in the C family,
everything in Go is passed by value. That is, a function always gets a
copy of the thing being passed, as if there were an assignment
statement assigning the value to the parameter. For instance, passing
an int value to a function makes a copy of the int, and passing a
pointer value makes a copy of the pointer, but not the data it points
to. (See the next section for a discussion of how this affects method
receivers.)

Map and slice values behave like pointers: they are descriptors that
contain pointers to the underlying map or slice data. Copying a map or
slice value doesn't copy the data it points to. Copying an interface
value makes a copy of the thing stored in the interface value. If the
interface value holds a struct, copying the interface value makes a
copy of the struct. If the interface value holds a pointer, copying
the interface value makes a copy of the pointer, but again not the
data it points to.