вторник, 2 ноября 2021 г.

Go для Java разработчиков: синтаксис

Декларации

Синтаксис объявления обратный по сравнению с Java. Вы пишете имя, а затем тип. Объявления типов можно легко читать слева направо.

Go Приблизительный эквивалент Java
var v1 int int v1 = 0;
var v2 *int Integer v2 = null;
var v3 string String v3 = "";
var v4 [10]int int[] v4 = new int[10];
(Массивы - это значения в Go.)
var v5 []int int[] v5 = null;
var v6 *struct{ a int } class C { int a; }
C v6 = null;
var v7 map[string]int HashMap v7;
v7 = null;
var v8 func(a int) int interface F {
int f(int a);
}
F v8 = null;

Объявления обычно принимают форму ключевого слова, за которым следует имя объявляемого объекта. Ключевое слово может иметь одно из следующих значений: const, type, var или func. Вы также можете использовать ключевое слово, за которым следует ряд объявлений в круглых скобках.

var (
    n int
    x float64
)

При объявлении функции вы должны либо указать имя для каждого параметра, либо не указывать имя для любого параметра; нельзя опускать одни имена и указывать другие. Вы можете сгруппировать несколько имен одного типа.

func f(i, j, k int, s, t string)

Переменная может быть инициализирована при ее объявлении. Когда это будет сделано, указание типа переменной разрешено, но не обязательно. Если тип не указан, по умолчанию используется тип выражения инициализации.

var v9 = *v2

Если переменная не инициализирована явно, необходимо указать тип. В этом случае он будет неявно инициализирован нулевым значением типа (0, nil, "" и т. д.). В Go нет неинициализированных переменных.

Краткие объявления

Внутри функции краткий синтаксис объявления доступен с :=. Утверждение

v10 := v1

то же самое что и

var v10 = v1

Типы функций

В Go функции - это объекты первого класса. Тип функции Go обозначает набор всех функций с одинаковыми параметрами и типами результатов.

type binOp func(int, int) int

var op binOp
add := func(i, j int) int { return i + j }

op = add
n = op(100, 200)  // n = 100 + 200

Множественное присвоение

Go допускает несколько назначений. Выражения справа оцениваются перед присвоением любому из операндов слева.

i, j = j, i  // Меняем местами i и j.

Функции могут иметь несколько возвращаемых значений, обозначенных списком в круглых скобках. Возвращенные значения могут быть сохранены путем присвоения списку переменных.

func f() (i int, pj *int) { ... }
v1, v2 = f()

Пустой идентификатор

Пустой идентификатор, представленный символом подчеркивания, позволяет игнорировать значения, возвращаемые многозначным выражением:

v1, _ = f()  // Игнорировать второе значение, возвращаемое f().

Точка с запятой и форматирование

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

В коде Go на практике используется очень мало точек с запятой. Технически все операторы Go заканчиваются точкой с запятой. Однако Go неявно вставляет точку с запятой в конце непустой строки, если строка явно не является неполной. Следствием этого является то, что в некоторых случаях Go не допускает разрыв строки. Например, вы не можете писать

func g()
{            // INVALID: "{" должно быть в предыдущей строке.
}

Точка с запятой будет вставлена ​​после g(), что приведет к тому, что это будет объявление функции, а не определение функции. Точно так же вы не можете писать

if n == 0 {
}
else {       // INVALID: "else {" должно быть в предыдущей строке.
}

Точка с запятой будет вставлена ​​после символа } перед else, что вызовет синтаксическую ошибку.

Условные утверждения

Go не использует круглые скобки вокруг условия оператора if, выражений оператора for или значения оператора switch. С другой стороны, он требует фигурных скобок вокруг тела оператора if или for.

if a < b { f() }
if (a < b) { f() }          // Скобки не нужны.
if (a < b) f()              // INVALID
for i = 0; i < 10; i++ {}
for (i = 0; i < 10; i++) {} // INVALID

Кроме того, if и switch принимают необязательный оператор инициализации, который обычно используется для установки локальной переменной.

if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}

For утверждения

Go не имеет инструкции while и do-while. Оператор for может использоваться с одним условием, что делает его эквивалентным оператору while. Полное исключение условия приводит к бесконечному циклу.

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

for i := 0; i < len(a); i++ { ... }

чтобы перебрать элементы a, мы также могли бы написать

for i, v := range a { ... }

Это присваивает i индексу, а v - значению последовательных элементов массива, среза или строки.

  • Для строк i - это индекс байта, а v - кодовая точка Unicode типа rune (rune - это псевдоним для int32).
  • Итерации по картам создают пары ключ-значение, тогда как каналы производят только одно значение итерации.

Break и continue

Подобно Java, Go разрешает break и continue для указания метки, но метка должна ссылаться на оператор for, switch или select.

Операторы switch

В операторе switch метки case не пропадают по умолчанию, но вы можете заставить их пропустить, завершив case оператором fallthrough.

switch n {
case 0: // пустое тело case
case 1:
    f() // f не вызывается, когда n == 0.
}

Но у case может быть несколько значений.

switch n {
case 0, 1:
    f() // f вызывается, если n == 0 || n == 1.
}

Значения в case могут быть любого типа, который поддерживает оператор сравнения равенства, например строки или указатели. Отсутствующее выражение switch эквивалентно выражению true.

switch {
case n < 0:
    f1()
case n == 0:
    f2()
default:
    f3()
}

Увеличение и уменьшение

++ и -- могут использоваться только как постфиксные операторы и только в операторах, но не в выражениях. Например, вы не можете написать n = i++.

Оператор defer

Оператор defer вызывает функцию, выполнение которой откладывается до момента возврата из окружающей функции.

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

f, err := os.Open("filename")
defer f.Close() // f будет закрыт, когда эта функция вернется.


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


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

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