Go: часть 4 – переменные

Предыдущая часть – типы данных.

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

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

Базовые типы переменных

Основываясь на базовых типах данных, рассмотренных в предыдущей части – в Go имеются следующие базовые типы переменных:

Sr.No Type & Description
1 byte

один октет (один байт, 8 бит)

2 int

ineteger для для конкретной машины

3 float32

число с плавающей точкой одинарной точности

Go также позволяет задавать различные другие типы переменных, такие как перечисления (Enumeration), указатели (Pointer), массивы (Array), стуктуры (Structure) и объединения (Union), которые мы рассмотрим в следующих частях. В этой части – сосредоточимся на базовых типах.

Определение переменной в Go

Определение, или описание, (definition) указывает компилятору на необходимость создать хранилище для переменной с определённым размером и расположением. В определении указывается тип данных и список из одной или более имён переменных:

var variable_list optional_data_type;

Тут optional_data_type является типом данных Go, таким как byte, int, float32 и т.д., а variable_list может содержать идентификаторы переменных (имена), разделённых запятыми.

Примеры определений  переменных:

var  i, j, k int;
var  c, ch byte;
var  f, salary float32;
d =  42;

В строке “var i, j, k;” описываются переменные i, j и k, что указывает компилятору на необходимость создания таких перменных с типом int(eger).

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

Инициализация выполняется с помощью символа равенства с последующей константой:

variable_name = value;

Например:

d = 3, f = 5;    // объявление переменных d и f. типа integer

Статическая типизация в Go

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

Пример:

package main

import "fmt"

func main() {
   var x float64
   x = 20.0
   fmt.Println(x)
   fmt.Printf("x is of type %T\n", x)
}

Результат выполнения:

$ go run static_dec.go 
20
x is of type float64

Динамическая типизация в Go

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

Пример:

package main

import "fmt"

func main() {
   var x float64 = 20.0

   y := 42 
   fmt.Println(x)
   fmt.Println(y)
   fmt.Printf("x is of type %T\n", x)
   fmt.Printf("y is of type %T\n", y)	
}

Обратите внимание, что инициализация y выполняется с помощью оператора :=, тогда как x – с помощью знака равенства.

Результат выполнения этого кода:

$ go run dynam_dec.go 
20
42
x is of type float64
y is of type int

Смешанное объявление в Go

Вы так же можете выполнить объявление нескольких переменных различных типов одной строкой, например:

package main

import "fmt"

func main() {
   var a, b, c = 3, 4, "foo"  
	
   fmt.Println(a)
   fmt.Println(b)
   fmt.Println(c)
   fmt.Printf("a is of type %T\n", a)
   fmt.Printf("b is of type %T\n", b)
   fmt.Printf("c is of type %T\n", c)
}

Результат выполнения:

$ go run mixed_decl.go 
3
4
foo
a is of type int
b is of type int
c is of type string

lvalues и rvalues в Go

В Go есть два типа выражений:

  • lvalue − выражение, которое ссылается на какой-то явный участок памяти называется “lvalue” (“Locator value“), при этом выражение может находится с любой стороны от оператора присваивания.
  • rvalue − термин r-value (“Raw value“?) применяется к данным, которые хранятся в каком-то участке памяти.

Переменные являются l-values, и могут указываться с левой стороны (тем не менее – не “left-value“, а “locator value“). Числовые литералы, в свою очередь, являются r-values, и не могут быть присвоены к чему-либо, и не должны быть указаны с левой стороны от оператора присваивания.

Т.е. следующее выражение будет корректным:

x = 20.0

Тогда как следующее вызовет ошибку компилятора:

10 = 20

[simterm]

$ go run mixed_decl.go 
# command-line-arguments
./mixed_decl.go:7:7: cannot assign to 10

[/simterm]

Продолжение – часть 5 – константы.