doulao5916 2019-03-08 22:20
浏览 41
已采纳

在struct元素上调用一个函数,该函数是一个nil指针

In Go, however, the function to be called by the Expression.Name() syntax is entirely determined by the type of Expression and not by the particular run-time value of that expression, including nil - copied

So we can call a method using a struct instance which is nil.

Consider the following program:

 package main

    import "fmt"

    type T struct {
        V int
        tt *T
    }

    func (t *T) hello() string {
       return "world"
   } 

    func main() {
        var t *T = nil
        fmt.Println(t, t.hello()) // <nil> world
        fmt.Println(t, t.tt.hello()) // panic
    }

Why fmt.Println(t, t.hello()) worked?

But

fmt.Println(t, t.tt.hello()) panicked?.

My understanding is that both t and t.tt are nil pointers. So t.tt.hello() should not panic as Calling a method on a nil struct pointer is allowed in golang.

  • 写回答

4条回答 默认 最新

  • douwu7563 2019-03-08 23:25
    关注

    My understanding is that both t and t.tt are nil pointers. So t.tt.hello() should not panic as Calling a method on a nil struct pointer is allowed in golang.

    Your "understanding" is wrong.t.tt should and does panic.


    Go 1.2 Release Notes (December 2013)

    Use of nil

    The language now specifies that, for safety reasons, certain uses of nil pointers are guaranteed to trigger a run-time panic. For instance, in Go 1.0, given code like

    type T struct {
        X [1<<24]byte
        Field int32
    }
    
    func main() {
        var x *T
        ...
    }
    

    the nil pointer x could be used to access memory incorrectly: the expression x.Field could access memory at address 1<<24. To prevent such unsafe behavior, in Go 1.2 the compilers now guarantee that any indirection through a nil pointer, such as illustrated here but also in nil pointers to arrays, nil interface values, nil slices, and so on, will either panic or return a correct, safe non-nil value. In short, any expression that explicitly or implicitly requires evaluation of a nil address is an error. The implementation may inject extra tests into the compiled program to enforce this behavior.

    Further details are in the design document.


    In short, any expression that explicitly or implicitly requires evaluation of a nil address is an error.

    Therefore, the following behavior is expected. The indirection for t.tt through a nil value of t fails with a panic.

    package main
    
    import "fmt"
    
    type T struct {
        V  int
        tt *T
    }
    
    func (t *T) hello() string {
        return "world"
    }
    
    type A struct {
        a int
    }
    
    func main() {
        var t *T = nil
        fmt.Println(t)            // nil
        fmt.Println(t.tt.hello()) // panic
    }
    

    Playground: https://play.golang.org/p/Szwx5MqNHkQ

    Output:

    <nil>
    panic: runtime error: invalid memory address or nil pointer dereference
    main.main()
        /tmp/sandbox136049644/main.go:21 +0x84
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?