Если M находится в наборе методов типа T, T.M - это функция, которая вызывается как обычная функция с теми же аргументами, что и M, с префиксом дополнительного аргумента, который является получателем метода.
MethodExpr = ReceiverType "." MethodName .
ReceiverType = Type .
Рассмотрим тип структуры T с двумя методами: Mv, чей получатель имеет тип T, и Mp, чей получатель имеет тип *T.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // получатель значение (value receiver)
func (tp *T) Mp(f float32) float32 { return 1 } // получатель указатель (pointer receiver)
var t T
Выражение
T.Mv
возвращает функцию, эквивалентную Mv, но с явным получателем в качестве первого аргумента; ее сигнатура
func(tv T, a int) int
Эта функция может вызываться с явным получателем, поэтому следующие пять вызовов эквивалентны:
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
Аналогично, выражение
(*T).Mp
возвращает значение функции, представляющее Mp с сигнатурой
func(tp *T, f float32) float32
Для метода с получателем значения можно получить функцию с получателем явного указателя, поэтому
(*T).Mv
возвращает значение функции, представляющее Mv с сигнатурой
func(tv *T, a int) int
Такая функция перенаправляется через получатель для создания значения, которое передается в качестве получателя базовому методу; метод не перезаписывает значение, адрес которого передается в вызове функции.
Последний случай, функция получения значения для метода указатель-получатель, является недопустимым, поскольку методы-указатели-получатели не входят в набор методов типа значения.
Значения функций, полученные из методов, вызываются с помощью синтаксиса вызова функций; получатель предоставляется в качестве первого аргумента вызова. То есть, учитывая, что f := T.Mv, f вызывается как f(t, 7), а не как t.f(7). Чтобы создать функцию, которая связывает получателя, используйте литерал функции или значение метода.
Допустимо получить значение функции из метода типа интерфейса. Результирующая функция принимает явный получатель этого типа интерфейса.
Читайте также:
- Спецификация Go: объявления методов
- Спецификация Go: литералы функций
- Спецификация Go: выражения (expressions) - операнды, квалифицированные идентификаторы
Комментариев нет:
Отправить комментарий