Первый заказ успешно выведет ID 1. Второй возвращает интерфейс с nil-указателем внутри, поэтому проверка order2!=nil проходит, а GetID вызывает panic при разыменовании.
Определение вывода программы при работе с nil‑интерфейсом и nil‑указателем
Первый заказ успешно выведет ID 1. Второй возвращает интерфейс с nil-указателем внутри, поэтому проверка order2!=nil проходит, а GetID вызывает panic при разыменовании.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо предсказать, какой текст будет выведен при выполнении программы, учитывая особенности сравнения интерфейсов с nil в Go.
type Order interface {
GetID() int
}
type orderStruct struct {
ID int
}
func (o *orderStruct) GetID() int {
return o.ID
}
func createOrder(shouldCreate bool) Order {
var order *orderStruct
fmt.Println("in createOrder: ", order == nil)
if shouldCreate {
order = &orderStruct{ID: 1}
}
return order
}
func main() {
order1 := createOrder(true)
if order1 != nil {
fmt.Printf("Order1 has ID: %d\n", order1.GetID())
} else {
fmt.Println("Order1 is nil")
}
order2 := createOrder(false)
if order2 != nil {
fmt.Printf("Order2 has ID: %d\n", order2.GetID())
} else {
fmt.Println("Order2 is nil")
}
}
Ответ
Первый заказ успешно выведет ID 1. Второй возвращает интерфейс с nil-указателем внутри, поэтому проверка order2!=nil проходит, а GetID вызывает panic при разыменовании.
В обоих вызовах сначала печатается, что локальный указатель равен nil. Далее для true появляется строка Order1 has ID: 1. Для false ветка Order2 is nil не выполняется: динамический тип *orderStruct делает интерфейс ненулевым. Исправление — при shouldCreate=false возвращать явный nil интерфейса, а при true — созданный объект.