一尘不染

定位指针,引用,取消引用的规则:

go

我是GoLang的新手,来自Delphi C ++世界-诚然对这种语言感到非常兴奋,我认为它将成为“下一件大事”。

我正在尝试了解Go解析器和编译器如何处理指针和引用-似乎找不到任何放置一些明确规则的地方。

例如,在下面的代码示例中,返回类型*list.List和局部变量l是指针类型,并且*在其声明中需要使用指针符号,但是在使用时不必取消引用它们:l.PushBack(i)。但是在同一代码中,输入参数value *int64被声明为指针,并且必须被取消引用才能正确使用:var i int64 = *value / 2

我认为这是因为list.List是引用类型,因此使用时,引用是隐式的,而引用是int64值类型,必须像对待值类型的任何指针一样进行处理,例如在C
++中:必须取消引用。

让我感到困惑的是,即使使用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

}

阅读 221

收藏
2020-07-02

共1个答案

一尘不染

List拥有*List接收者的所有方法:(http://golang.org/pkg/container/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总是按值传递。

2020-07-02