dsj0312 2014-05-01 18:40
浏览 36
已采纳

在Go中为接口类型分配<nil>为什么有效?

http://play.golang.org/p/_GP3RZTh4Q

package main

import "fmt"

type TesterInterface interface{
    Yell()
}

type Tester struct{}

func (t Tester) Yell() {
    fmt.Println("HELLO")
}

func main() {
    var t TesterInterface
    t = Tester{}
    t.Yell()
    t = nil
    t.Yell()
}

I would expect the compiler to complain about line 19 (t = nil), since nil doesn't implement Yell(), however the program runs and provides the following output:

HELLO
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0xffffffff addr=0x0 pc=0x201a9]

goroutine 1 [running]:
runtime.panic(0xef060, 0x1b3d44)
    /tmp/sandbox/go/src/pkg/runtime/panic.c:266 +0xe0
runtime.panicstring(0x1b3d44, 0x1b85)
    /tmp/sandbox/go/src/pkg/runtime/panic.c:489 +0x120
runtime.sigpanic()
    /tmp/sandbox/go/src/pkg/runtime/os_nacl.c:254 +0x80
main.main()
    /tmpfs/gosandbox-229cdcdf_329829af_705be907_f12cf4dc_ed51e32e/prog.go:20 +0xa9
runtime.main()
    /tmp/sandbox/go/src/pkg/runtime/proc.c:220 +0x1c0
runtime.goexit()
    /tmp/sandbox/go/src/pkg/runtime/proc.c:1394

goroutine 2 [syscall]:
runtime.notetsleepg(0xfeefdf88, 0x0, 0xf8475800, 0xd)
    /tmp/sandbox/go/src/pkg/runtime/lock_sema.c:254 +0xa0
runtime.MHeap_Scavenger()
    /tmp/sandbox/go/src/pkg/runtime/mheap.c:463 +0xc0
runtime.goexit()
    /tmp/sandbox/go/src/pkg/runtime/proc.c:1394
created by runtime.main
    /tmp/sandbox/go/src/pkg/runtime/proc.c:179
 [process exited with non-zero status]

Program exited.

Why does the compiler consider it legal to assign nil to an interface?

Additionally, from the Go-docs:

A variable of interface type can store a value of any type with a method set that is any superset of the interface.

How does "nil" contain a method set that is a superset of TesterInterface? The docs go on to say that

The value of an uninitialized variable of interface type is nil.

But this seems to contradict the first statement.

  • 写回答

2条回答 默认 最新

  • drsh30452 2014-05-01 19:22
    关注

    It is always dicey when you ask questions like "why does the compiler consider it legal…" The answer, as usual, is because that's the language, and every interface accepts the nil value. But there are more sides of this: the implementation of interfaces, and how Go would work if it were not this way.

    Starting with the latter, consider the problem if nil were not a legal value for interfaces. How would you replace the common idiom:

    func Something() error {
        ...
        return nil
    }
    

    This relies on the fact that nil is a valid error. Similarly, it is very common that pointers satisfy an interface. If nil did not also satisfy the interface, how would you return the nil pointer? Remember, nil is just a value.

    To the implementation, see Why is my nil error value not equal to nil? The key point is that an interface is made up of a tuple of type and value, and for every interface, the tuple (nil, nil) is valid.

    I assume you agree that a "typed nil" (i.e. a nil of some specific pointer type) should be assignable to an interface that is implemented by its pointer type, correct? So interfaces must be treated as though they could be nil, and you must nil-check them in exactly the same ways that you nil-check pointers. So there is no safety benefit to excluding the untyped nil, but you'd break many useful things you can do with interfaces (like return "no error").

    (There's a slight subtlty to this last part. Read carefully again "Why is my nil error value not equal to nil?" and you'll realize that you can't trivially nil-check an interface that holds a typed nil value. You can only do that by type asserting the interface into its underlying pointer type or using reflect on it. This doesn't dramatically change the point, but I didn't want to gloss over that problem.)


    EDIT

    Based on @newacct's comments below, struck some extraneous points.

    PeterSO's answer is also very important. Every type must have a zero value. What else would the zero value for an interface be but nil?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料