Проблема вызова метода у значения, полученного из map

Элемент map не адресуем, поэтому для значения Bar нельзя автоматически вызвать метод с receiver *Bar. Храните указатели, используйте value receiver или работайте с локальной копией.

Короткий ответ

Что ответить на собеседовании

Элемент map не адресуем, поэтому для значения Bar нельзя автоматически вызвать метод с receiver *Bar. Храните указатели, используйте value receiver или работайте с локальной копией.

Подробный разбор

Ответ с пояснениями

Условие

В примере пытаются вызвать метод Fizz() у элемента, полученного из map, но компилятор выдаёт ошибку.

Почему происходит ошибка

Метод Fizz объявлен с указательным получателем *Bar. При обращении к элементу карты m["bar"] возвращается значение типа Bar, а не указатель. Значения, полученные из map, не являются адресуемыми, поэтому компилятор не может автоматически взять их адрес и вызвать метод с указательным получателем.

Варианты исправления

  1. Хранить в карте указатели на 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()
}
  1. Сделать получатель метода значением (не указателем):
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()
}
  1. Скопировать значение в переменную, взять её адрес и вызвать метод:
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 перед вызовом метода.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее