douwenan9849 2013-12-31 00:16
浏览 51
已采纳

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

I am new to GoLang, coming from the Delphi, C++ world - admittedly very excited about this language, which I think is destined to become "the next big thing".

I am trying to get a handle around how the Go parser and compiler handle pointers and references - can't seem to find any place where some clear rules are laid out.

In the below code sample for example, the return type *list.List and the local variable l are pointer types and require the pointer symbol * in their declarations, but they don't have to be dereferenced in use: l.PushBack(i). But in this same code the input parameter value *int64 is declared as a pointer and has to be dereferenced to be used properly: var i int64 = *value / 2

I assume that this is because list.List is a reference type, so the dereferencing is implicit when used, while int64 is a value type and must be handled just as any pointer to a value type, as in C++ for example: It must be dereferenced.

What is confusing to me is that even though *list.List has to be declared as a pointer type using *, when using the list instance, dereferencing is not required. This had me quite confused initially. Is that "just the way it is", or am I missing something?

Sample:

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

}
  • 写回答

1条回答 默认 最新

  • dongtuo4723 2013-12-31 01:15
    关注

    All of the methods for a List have *List receivers: (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{}
    

    In your example l is of type *List, so there's no need to dereference them.

    Suppose, instead, that you had something like this:

    type A struct{}
    func (a  A) X() {
        fmt.Println("X")
    }
    func (a *A) Y() {
        fmt.Println("Y")
    }
    

    You are allowed to write:

    a := A{}
    a.X()
    a.Y() // == (&a).Y()
    

    Or you can do the following:

    a := &A{}
    a.X() // same like == (*a).X()
    a.Y()
    

    But it only works for method receivers. Go will not automatically convert function arguments. Given these functions:

    func A(x *int) {
        fmt.Println(*x)
    }
    func B(y int) {
        fmt.Println(y)
    }
    

    This is invalid:

    A(5)
    

    You have to do this:

    var x int 
    A(&x)
    

    This is also invalid:

    var y *int
    B(y)
    

    You have to do this:

    B(*y)
    

    Unlike C# or Java, when it comes to structs, Go does not make a distinction between reference and value types. A *List is a pointer, a List is not. Modifying a field on a List only modifies the local copy. Modifying a field on a *List modifies all "copies". (cause they aren't copies... they all point to the same thing in memory)

    There are types which seem to hide the underlying pointer (like a slice contains a pointer to an array), but Go is always pass by value.

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

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置