我是GoLang的新手,来自Delphi C ++世界-诚然对这种语言感到非常兴奋,我认为它将成为“下一件大事”。
我正在尝试了解Go解析器和编译器如何处理指针和引用-似乎找不到任何放置一些明确规则的地方。
例如,在下面的代码示例中,返回类型*list.List和局部变量l是指针类型,并且*在其声明中需要使用指针符号,但是在使用时不必取消引用它们:l.PushBack(i)。但是在同一代码中,输入参数value *int64被声明为指针,并且必须被取消引用才能正确使用:var i int64 = *value / 2
*list.List
l
*
l.PushBack(i)
value *int64
var i int64 = *value / 2
我认为这是因为list.List是引用类型,因此使用时,引用是隐式的,而引用是int64值类型,必须像对待值类型的任何指针一样进行处理,例如在C ++中:必须取消引用。
list.List
int64
让我感到困惑的是,即使使用list实例必须*list.List使用声明为指针类型*,也不需要取消引用。一开始这让我很困惑。是“就这样”,还是我错过了什么?
样品:
func GetFactors(value *int64) *list.List { l := list.New() l.PushBack(*value) var i int64 = *value / 2 for ; i > 1; i-- { if *value%i == 0 { l.PushBack(i) } } return l }
List拥有*List接收者的所有方法:(http://golang.org/pkg/container/list/)
List
*List
func (l *List) Back() *Element func (l *List) Front() *Element func (l *List) Init() *List ... func (l *List) Remove(e *Element) interface{}
在您的示例l中,类型为*List,因此无需取消引用它们。
假设您有这样的事情:
type A struct{} func (a A) X() { fmt.Println("X") } func (a *A) Y() { fmt.Println("Y") }
您可以写:
a := A{} a.X() a.Y() // == (&a).Y()
或者,您可以执行以下操作:
a := &A{} a.X() // same like == (*a).X() a.Y()
但这仅适用于方法接收器。Go不会自动转换函数参数。鉴于以下功能:
func A(x *int) { fmt.Println(*x) } func B(y int) { fmt.Println(y) }
这是无效的:
A(5)
您必须这样做:
var x int A(&x)
这也是无效的:
var y *int B(y)
B(*y)
与C#或Java不同,当涉及到结构时,Go不会在引用类型和值类型之间进行区分。A *List是一个指针,a List不是。List仅修改字段会修改本地副本。修改修改后的字段*List会修改所有“副本”。(因为它们不是副本…它们都指向内存中的同一件事)
有些类型似乎隐藏了基础指针(例如切片包含指向数组的指针),但是Go总是按值传递。