четверг, 6 июня 2019 г.

Спецификация Go: значения метода

Если выражение x имеет статический тип T и M находится в наборе методов типа T, x.M называется значением метода. Значение метода x.M - это значение функции, которое можно вызывать с теми же аргументами, что и вызов метода x.M. Выражение x вычисляется и сохраняется во время оценки значения метода; сохраненная копия затем используется в качестве получателя в любых вызовах, которые могут быть выполнены позже.

Тип T может быть интерфейсным или неинтерфейсным типом.

Рассмотрим тип структуры 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
var pt *T
func makeT() T

Выражение

t.Mv

дает значение функции типа

func(int) int

Следующие два вызова эквивалентны:

t.Mv(7)
f := t.Mv; f(7)

Аналогично, выражение

pt.Mp

дает значение функции типа

func(float32) float32

Как и в случае селекторов, ссылка на неинтерфейсный метод с получателем значения, использующим указатель, автоматически разыменует этот указатель: pt.Mv эквивалентен (*pt).Mv.

Как и в случае вызовов методов, ссылка на неинтерфейсный метод с получателем указателя, использующим адресуемое значение, автоматически получит адрес этого значения: t.Mp эквивалентно (&t).Mp.

f := t.Mv; f(7)   // то же что и t.Mv(7)
f := pt.Mp; f(7)  // то же что и pt.Mp(7)
f := pt.Mv; f(7)  // то же что и (*pt).Mv(7)
f := t.Mp; f(7)   // то же что и (&t).Mp(7)
f := makeT().Mp   // недопустимо: результат makeT() не адресуем

Хотя в приведенных выше примерах используются неинтерфейсные типы, также допустимо создавать значение метода из значения интерфейсного типа.

var i interface { M(int) } = myVal
f := i.M; f(7)  // то же что и i.M(7)


Читайте также:


Комментариев нет:

Отправить комментарий