почему назначение интерфейса с указателем, а затем адрес показывает другое поведение в Голанге - PullRequest
0 голосов
/ 11 декабря 2018

Я новичок в Голанге.Я начинаю с тура по го.Вот ссылка go площадка

Вот код:

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()
}

Это паника

Паника: ошибка во время выполнения: недействительноадрес памяти или разыменование нулевого указателя [сигнал SIGSEGV: код нарушения сегментации = 0xffffffff addr = 0x0 pc = 0xd3ea6] маршрут 1 [выполняется]: основной. (* T) .M (0x0, 0x434070) /tmp/sandbox696069628/main.go:15 + 0x26 main.main () /tmp/sandbox696069628/main.go:24 + 0x40

Однако при изменении

var t *T 
i = t

на

var t T 
i = &t

Это больше не паникует

Разве поведение не должно быть одинаковым в обоих случаях.Если нет, то почему?

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Вы объявляете, но явно не определяете переменную с именем t в обоих случаях.Если вы не укажете значение, нулевое значение для типа переменной будет присвоено

Нулевое значение для всех типов указателей, включая *T, равно nil.Нулевое значение для типа структуры - это значение этой структуры со всеми полями, для которых установлены нулевые значения.

Когда хранилище выделено для переменной [...] и не предусмотрена явная инициализация,переменной или значению присваивается значение по умолчанию.Каждый элемент такой переменной или значения устанавливается в нулевое значение для его типа: false для логических значений, 0 для числовых типов, «» для строк и nil для указателей, функций, интерфейсов, слайсов, каналов и карт.Эта инициализация выполняется рекурсивно, поэтому, например, каждый элемент массива структур будет обнулять свои поля, если не указано значение.

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

Следовательно, это сохраняет ноль взначение интерфейса 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() называется.

0 голосов
/ 11 декабря 2018

Вы не инициализировали T.
Сделайте это:

var t *T = &T{"Hello World"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...