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条)

报告相同问题?

悬赏问题

  • ¥15 数学的三元一次方程求解
  • ¥20 iqoo11 如何下载安装工程模式
  • ¥15 本题的答案是不是有问题
  • ¥15 关于#r语言#的问题:(svydesign)为什么在一个大的数据集中抽取了一个小数据集
  • ¥15 C++使用Gunplot
  • ¥15 这个电路是如何实现路灯控制器的,原理是什么,怎么求解灯亮起后熄灭的时间如图?
  • ¥15 matlab数字图像处理频率域滤波
  • ¥15 在abaqus做了二维正交切削模型,给刀具添加了超声振动条件后输出切削力为什么比普通切削增大这么多
  • ¥15 ELGamal和paillier计算效率谁快?
  • ¥15 蓝桥杯单片机第十三届第一场,整点继电器吸合,5s后断开出现了问题