为什么用指针分配接口,然后一个地址在Golang中显示不同的行为

时间:2018-12-11 10:24:14

标签: go

我是golang的新手。我从游览开始。 这是go playground link

这是代码:

let port_string = DEFAULT_LISTENER_PORT.to_string();
let matches = App::new(env!("CARGO_PKG_NAME"))
    .version(env!("CARGO_PKG_VERSION"))
    .arg(Arg::with_name("port")
         .short("p")
         .value_name("PORT")
         .default_value(&port_string)
    ).get_matches();

这很着急

  

紧急:运行时错误:无效的内存地址或nil指针   取消引用       [信号SIGSEGV:细分违规代码= 0xffffffff addr = 0x0       pc = 0xd3ea6]       goroutine 1 [正在运行]:       main。(* T).M(0x0,0x434070)/tmp/sandbox696069628/main.go:15 + 0x26       main.main()/tmp/sandbox696069628/main.go:24 + 0x40

但是当我更改

package main

import "fmt"

type I interface {
    M()
}

type T struct {
    S string
}

func (t *T) M() {

    fmt.Println(t.S)
}

func main() {
    var i I

    var t *T 
    i = t

    i.M()
}

var t *T 
i = t

它不再惊慌

两种情况下的行为都不应相似。如果没有,为什么?

2 个答案:

答案 0 :(得分:3)

在两种情况下,您都在声明但未明确定义名为t的变量。如果您未指定值,则会为变量的类型分配零值

所有指针类型(包括*T)的零值为nil。结构类型的零值是该结构的值,所有字段均设置为零。

  

当为变量[...]分配存储空间且未提供显式初始化时,该变量或值将被赋予默认值。此类变量或值的每个元素的类型均设置为零:布尔值为false,数字类型为0,字符串为“”,指针,函数,接口,切片,通道和映射为nil。初始化是递归完成的,因此,例如,如果未指定任何值,则结构数组的每个元素的字段都将为零。

https://golang.org/ref/spec#The_zero_value

因此,这会将nil存储在接口值i中:

var i interface{ M() }
var t *T 
i = t
// i stores nil

这会在接口值i中存储一个结构值:

var i interface{ M() }
var t T 
i = t
// i stores T{S:""}

因此,在第一种情况下,(nil).M()被称为(恐慌),在第二种情况下,(T{}).M()被称为

答案 1 :(得分:2)

您没有初始化T。
这样做:

var t *T = &T{"Hello World"}