Показаны сообщения с ярлыком выражения в Go. Показать все сообщения
Показаны сообщения с ярлыком выражения в Go. Показать все сообщения

воскресенье, 16 июня 2019 г.

Спецификация Go: утверждения выражений (expression statements)

За исключением определенных встроенных функций, вызовы функций и методов и операции получения могут появляться в контексте утверждения (statement context). Такие утверждения могут быть заключены в скобки.

ExpressionStmt = Expression .

Следующие встроенные функции не разрешены в контексте утверждения:

append cap complex imag len make new real
unsafe.Alignof unsafe.Offsetof unsafe.Sizeof

Примеры утверждений выражений:

h(x+y)
f.Close()
<-ch
(<-ch)
len("foo")  // недопустимо, если len является встроенной функцией


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


пятница, 7 июня 2019 г.

Спецификация Go: выражения срезов (slice expressions)

Выражения срезов создают подстроку или срез из строки, массива, указателя на массив или среза. Существует два варианта: простая форма, которая определяет нижнюю и верхнюю границу, и полная форма, которая также определяет границу емкости.

Простые выражения срезов (slice expressions)

Для строки, массива, указателя на массив или среза a, первичное выражение

a[low : high]

создает подстроку или срез. Индексы low и high выбирают, какие элементы операнда a появляются в результате. Результат имеет индексы, начинающиеся с 0, а длина равна high - low. После нарезки (slicing) массива a

a := [5]int{1, 2, 3, 4, 5}
s := a[1:4]

срез s имеет тип []int, длину 3, емкость 4 и элементы

s[0] == 2
s[1] == 3
s[2] == 4

Для удобства любой из индексов может быть опущен. Отсутствующий нижний индекс по умолчанию равен нулю; отсутствующий верхний индекс по умолчанию равен длине нарезанного операнда:

a[2:]  // тоже что и a[2 : len(a)]
a[:3]  // тоже что и a[0 : 3]
a[:]   // тоже что и a[0 : len(a)]

Если a - указатель на массив,
a[low : high] является сокращением для (*a)[low : high].

Для массивов или строк индексы находятся в диапазоне, если 0 <= low <= high <= len(a), в противном случае они находятся вне диапазона. Для срезов верхняя граница индекса - это ограничение емкости cap(a), а не длина. Постоянный индекс должен быть неотрицательным и представим значением типа int; для массивов или постоянных строк постоянные индексы также должны находиться в диапазоне. Если оба индекса постоянны, они должны удовлетворять требованию low <= high (нижний <= верхний). Если индексы выходят за пределы диапазона во время выполнения (run time), возникает паника во время выполнения (run-time panic).

За исключением нетипизированных строк, если нарезанный операнд является строкой или срезом, результатом операции среза будет непостоянное значение того же типа, что и операнд. Для нетипизированных строковых операндов результатом является непостоянное значение типа string. Если нарезанный операнд является массивом, он должен быть адресуемым, а результатом операции среза является срез с элементом того же типа, что и массив.

Если нарезанный операнд валидного выражения среза является нулевым срезом, результатом является нулевой срез. В противном случае, если результатом является срез, он разделяет свой базовый массив с операндом.

Полные выражения срезов

Для массива, указателя на массив или среза (но не строки), первичное выражение

a[low : high : max]

строит срез того же типа, с той же длиной и элементами, что и простое выражение среза a[low : high]. Кроме того, оно контролирует емкость результирующего среза, устанавливая его равным max - low. Только первый индекс может быть опущен; по умолчанию 0. После нарезки массива a

a := [5]int{1, 2, 3, 4, 5}
t := a[1:3:5]

срез t имеет тип []int, длину 2, емкость 4 и элементы

t[0] == 2
t[1] == 3

Что касается простых выражений среза, если a является указателем на массив, то a[low : high : max] является сокращением для (*a)[low : high : max]. Если нарезанный операнд является массивом, он должен быть адресуемым.

Индексы находятся в диапазоне, если 0 <= low <= high <= max <= cap(a), в противном случае они находятся вне диапазона. Постоянный индекс должен быть неотрицательным и представим значением типа int; для массивов постоянные индексы также должны находиться в диапазоне. Если несколько индексов являются постоянными, присутствующие константы должны находиться в диапазоне относительно друг друга. Если индексы выходят за пределы диапазона во время выполнения, возникает паника во время выполнения.


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


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

Спецификация Go: выражения методов (method expressions)

Если 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). Чтобы создать функцию, которая связывает получателя, используйте литерал функции или значение метода.

Допустимо получить значение функции из метода типа интерфейса. Результирующая функция принимает явный получатель этого типа интерфейса.


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


среда, 5 июня 2019 г.

Спецификация Go: выражения (expressions) - операнды, квалифицированные идентификаторы

Выражение определяет вычисление значения, применяя операторы и функции к операндам.

Операнды

Операнды обозначают элементарные значения в выражении. Операндом может быть литерал, (возможно, квалифицированный) непустой идентификатор, обозначающий константу, переменную или функцию или выражение в скобках.

Пустой идентификатор может появляться как операнд только в левой части назначения.

Operand     = Literal | OperandName | "(" Expression ")" .
Literal     = BasicLit | CompositeLit | FunctionLit .
BasicLit    = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
OperandName = identifier | QualifiedIdent.

Квалифицированные идентификаторы

Квалифицированный идентификатор - это идентификатор с префиксом имени пакета. И имя пакета, и идентификатор не должны быть пустыми.

QualifiedIdent = PackageName "." identifier .

Квалифицированный идентификатор обращается к идентификатору в другом пакете, который должен быть импортирован. Идентификатор должен быть экспортирован и объявлен в блоке пакета этого пакета.

math.Sin    // обозначает функцию Sin в пакете math


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