Элемент map не адресуем, поэтому для значения Bar нельзя автоматически вызвать метод с receiver *Bar. Храните указатели, используйте value receiver или работайте с локальной копией.
Проблема вызова метода у значения, полученного из map
Элемент map не адресуем, поэтому для значения Bar нельзя автоматически вызвать метод с receiver *Bar. Храните указатели, используйте value receiver или работайте с локальной копией.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В примере пытаются вызвать метод Fizz() у элемента, полученного из map, но компилятор выдаёт ошибку.
Почему происходит ошибка
Метод Fizz объявлен с указательным получателем *Bar. При обращении к элементу карты m["bar"] возвращается значение типа Bar, а не указатель. Значения, полученные из map, не являются адресуемыми, поэтому компилятор не может автоматически взять их адрес и вызвать метод с указательным получателем.
Варианты исправления
- Хранить в карте указатели на
Bar:
package main
import "fmt"
type Bar struct{}
func (b *Bar) Fizz() {
fmt.Println("buzz")
}
func main() {
m := map[string]*Bar{"bar": &Bar{}}
m["bar"].Fizz()
}
- Сделать получатель метода значением (не указателем):
package main
import "fmt"
type Bar struct{}
func (b Bar) Fizz() {
fmt.Println("buzz")
}
func main() {
m := map[string]Bar{"bar": Bar{}}
m["bar"].Fizz()
}
- Скопировать значение в переменную, взять её адрес и вызвать метод:
package main
import "fmt"
type Bar struct{}
func (b *Bar) Fizz() {
fmt.Println("buzz")
}
func main() {
m := map[string]Bar{"bar": Bar{}}
v := m["bar"]
(&v).Fizz()
}
Исходный код, вызывающий ошибку
package main
import "fmt"
type Bar struct{}
func (b*Bar)Fizz(){
fmt.Println("buzz")
}
func main() {
m :=map[string]Bar{"bar": Bar{}}
m["bar"].Fizz()
}
Ответ
Элемент map не адресуем, поэтому для значения Bar нельзя автоматически вызвать метод с receiver *Bar. Храните указатели, используйте value receiver или работайте с локальной копией.
Все три направления уже показаны в условии. Вариант с локальной переменной требует m["bar"] = v, если метод изменяет поля и результат должен сохраниться в map. Value receiver тоже получает копию и не подходит для изменения исходного объекта. В map указателей отдельно учитывайте отсутствие ключа и nil перед вызовом метода.