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

Спецификация Go: первичные выражения (primary expressions), селекторы (selectors)

Первичные выражения (primary expressions) являются операндами для унарных и двоичных выражений.

PrimaryExpr =
  Operand |
  Conversion |
  MethodExpr |
  PrimaryExpr Selector |
  PrimaryExpr Index |
  PrimaryExpr Slice |
  PrimaryExpr TypeAssertion |
  PrimaryExpr Arguments .

Selector       = "." identifier .
Index          = "[" Expression "]" .
Slice          = "[" [ Expression ] ":" [ Expression ] "]" |
                 "[" [ Expression ] ":" Expression ":" Expression "]" .
TypeAssertion  = "." "(" Type ")" .
Arguments      = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .

Примеры первичных выражений:

x
2
(s + ".txt")
f(3.1415, true)
Point{1, 2}
m["foo"]
s[i : j + 1]
obj.color
f.p[i].x()

Селекторы (Selectors)

Для первичного выражения (primary expression) x, которое не является именем пакета, выражение селектора (selector expression)

x.f

обозначает поле или метод f значения x (или иногда *x). Идентификатор f называется селектором (поля или метода); это не должен быть пустой идентификатор. Тип выражения селектора (selector expression) - это тип f.

Селектор f может обозначать поле или метод f типа T, или он может ссылаться на поле или метод f вложенного встроенного (embedded) поля T. Число встроенных (embedded) полей, пройденных для достижения f, называется его глубиной (depth) в T. Глубина поля или метода f, объявленного в T, равна нулю. Глубина поля или метода f, объявленного во встроенном поле A в T, равна глубине f в A плюс один.

Следующие правила применяются к селекторам:

  1. Для значения x типа T или *T, где T не является указателем или интерфейсным типом, x.f обозначает поле или метод на самой малой глубине в T, где есть такое f. Если нет точно одного f с наименьшей глубиной, выражение селектора (selector expression) недопустимо.
  2. Для значения x типа I, где I является типом интерфейса, x.f обозначает фактический метод с именем f динамического значения x. Если в наборе методов I нет метода с именем f, выражение селектора (selector expression) недопустимо.
  3. В качестве исключения, если тип x является определенным типом указателя и (*x).f является допустимым выражением селектора, обозначающим поле (но не метод), x.f является сокращением для (*x).f.
  4. Во всех остальных случаях x.f является недопустимым.
  5. Если x имеет тип указателя и имеет значение nil, а x.f обозначает поле структуры, назначение или оценка (evaluating) x.f вызывает панику во время выполнения (run-time panic).
  6. Если x имеет тип интерфейса и имеет значение nil, вызов или оценка метода x.f вызывает панику во время выполнения.

Например, для данных объявлений:

type T0 struct {
  x int
}

func (*T0) M0()

type T1 struct {
  y int
}

func (T1) M1()

type T2 struct {
  z int
  T1
  *T0
}

func (*T2) M2()

type Q *T2

var t T2     // при условии что t.T0 != nil
var p *T2    // при условии что p != nil и (*p).T0 != nil
var q Q = p

можно написать

t.z          // t.z
t.y          // t.T1.y
t.x          // (*t.T0).x

p.z          // (*p).z
p.y          // (*p).T1.y
p.x          // (*(*p).T0).x

q.x          // (*(*q).T0).x        (*q).x это допустимый селектор поля

p.M0()       // ((*p).T0).M0()      M0 ожидает *T0 получатель
p.M1()       // ((*p).T1).M1()      M1 ожидает T1 получатель
p.M2()       // p.M2()              M2 ожидает *T2 получатель
t.M2()       // (&t).M2()           M2 ожидает *T2 получатель

но следующее недопустимо:

q.M0()       // (*q).M0 допустимо, но не селектор поля


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


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

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