Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лр1_Go.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
559.1 Кб
Скачать

Задание 1.4 Реализуйте вышеописанный пример, используйте различные варианты присваивания значений переменной X (латинские и русские символы).

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

Константы объявляются с помощью ключевого слова const. Приведем несколько примеров объявлений:

const limit = 512 // константа; совместима с любыми числовыми типами

const top uint16 = 1421 // константа; тип: uint16

Обычной практикой считается не указывать тип явно, если только не требуется использовать какой-то конкретный тип, который не определяется компилятором. Типизированные числовые константы (такие как top в примере выше) могут использоваться только в выражениях с числовыми значениями того же типа (если явно не преобразовывать их тип). Нетипизированные числовые константы могут использоваться в выражениях с числовыми значениями любых встроенных типов (например, константу limit можно использовать в выражениях с целыми или вещественными числами).

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

Например, приведенные ниже фрагменты объявляют одни и те же константы:

const Zero = 0

const One = 1

const Two = 2

const (

Zero = 0

One = 1

Two = 2

)

const (

Zero = iota // 0

One // 1

Two // 2

)

Генератор констант iota – это предопределенный идентификатор, представляющий последовательность нетипизированных целочисленных значений. Значение этого идентификатора сбрасывается в нуль при встрече каждого нового ключевого слова const и увеличивается для каждой последующей константы в группе. Поэтому в правом фрагменте выше все константы получат значение iota (One и Two – неявно). Объявление константы Zero следует за ключевым словом const, значение iota будет сброшено в нуль и присвоено константе Zero. Константа One также получит значение iota, но на этот раз оно будет увеличено на 1. Аналогично константа Two получит значение iota, которое к этому моменту станет равно 2.

Если в правом фрагменте убрать явное присваивание значения iota, константа Zero получит значение 0, константа One получит значение константы Zero, и константа Two получит значение константы One – все константы получат значение 0. Аналогично, если константе Zero присвоить значение 2, все константы в этой группе получат значение 2. Eсли константе One присвоить значение 4, константа Zero получит значение 0 (так как она является первой в группе и ей явно не назначено какое-либо другое значение или значение iota), константа One получит значение 4 (указанное явно), и константа Two значение предыдущей константы, т.е. 4.

Рассмотрим объявление переменных в Go. Объявление var создает переменную определенного типа, назначает ей имя и при­сваивает начальное значение. Каждое объявление имеет общий вид var имя тип = выражение (тип или = выражение может отсутствовать). Если опущен тип, то он определяется из инициализирующего выражения. Если же опущено выражение, то начальным значением является нулевое значение для данного типа:

  • для чисел  0;

  • для булевых переменных  false;

  • для строк  "" (пустая строка);

  • для интерфейсов и ссылочных типов (срезов, указателей, отображений, каналов, функций)  nil;

  • для составного типа (массивы или структура)  нулевые значения всех его элементов или полей.

Рассмотрим примеры объявления переменных:

var i int // переменная; значение 0; тип: int

var debug = false // переменная; определяемый компилятором тип: bool

Несколько переменных можно объявить и (необязательно) инициализировать в одном объявлении var, используя соответствующий список выражений. Пропущенный тип позволяет объявлять несколько переменных разных типов, например:

var i, j, k int // int, int, int

var s, b, f = "строка”, true, 2.3 // string, bool, float64

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

Множество переменных может также быть инициализировано с помощью вызова функции, возвращающей несколько значений, например:

var f, err = os.Open(name) // os.Open возвращает имя файла и ошибку

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

first := -19 // переменная; определяемый компилятором тип: int

last := int64(9876543210) // переменная; тип: int64

result := true // переменная; определяемый компилятором тип: bool

step := 1.5 // переменная; определяемый компилятором тип: float64

str := "строка" // переменная; определяемый компилятором тип: string

В одном кратком объявлении можно объявить и инициализировать несколько переменных, например i, j := 0, 1 // i = 0, j = 1

Краткие объявления переменных могут использоваться для вызовов функций наподобие os.Open, которые возвращают два или больше значений, например:

f, err := os.Open(name)

if err != nil {

return err

}

// ... использование f

f.Close()

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

in, err := os.Open(infile) //объявляем in и err

out, err := os.Create(outfile) //объявляем out и присваиваем значение err

Краткое объявление переменной должно объявлять по крайней мере одну новую переменную, например, приведенный ниже код не компилируется:

in, err := os.Open(infile)

in, err:= os.Create(outfile) // Ошибка: нет новой переменной

//(для устранения ошибки следует

//использовать присваивание «=»)

Время жизни переменной  это интервал времени выполнения программы, в течение которого она существует. Переменные уровня пакета существуют все время работы программы. Локальные переменные имеют динамическое время жизни: новый экземпляр создается всякий раз, когда выполняется оператор объявления, и переменная живет до тех пор, пока она становится недоступной, после чего выделенная для нее память может быть использована повторно. Параметры и результаты функций являются локальными переменными  они создаются всякий раз, когда вызывается их функция.

Рассмотрим логические значения и выражения в Go. В языке Go имеются два встроенных логических значения, true и false, оба относятся к типу bool. Кроме того, в Go поддерживаются стандартные логические операторы и операторы сравнения, возвращающие результат типа bool (таблица 1.2).

Таблица 1.2  Логические операторы и операторы сравнения

Оператор

Описание/результат

!b

Оператор логического отрицания. Вернет false, если b имеет значение true

a || b

Оператор «логическое ИЛИ» с сокращенным порядком вычисления. Вернет true, если одно из подвыражений, a или b, вернет true

a && b

Оператор «логическое И» с сокращенным порядком вычисления. Вернет true, если оба подвыражения, a и b, вернут true

x < y

Вернет true, если значение выражения x меньше значения выражения y

x <= y

Вернет true, если значение выражения x меньше или равно значению выражения y

x == y

Вернет true, если значение выражения x равно значению выражения y

x != y

Вернет true, если значение выражения x не равно значению выражения y

x >= y

Вернет true, если значение выражения x больше или равно значению выражения y

x > y

Вернет true, если значение выражения x больше значения выражения y

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

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

Рассмотрим числовые типы данных в Go. Все числовые типы считаются отличными друг от друга, то есть к числовым значениям разных типов (например, к значениям типов int32 и int) нельзя применять двухместные арифметические операторы или операторы сравнения.

Чтобы выполнить арифметическую операцию или сравнить два числовых значения разных типов, необходимо выполнить преобразование типов, обычно к большему типу, чтобы избежать потери точности. Синтаксис преобразования типа имеет вид: тип(значение). Например:

const factor = 3 // Константа factor совместима со всеми числовыми типами

i := 20000 // i автоматически получит тип int

i *= factor

j := int16(20) // j получит тип int16; то же, что и: var j int16 = 20

i += int(j) // Типы должны совпадать, поэтому преобразование обязательно

k := uint8(0) // То же, что и: var k uint8

k = uint8(i) // Успех, но k получит значение i, усеченное до 8 бит

fmt.Println(i, j, k) // Выведет: 60020 20 116

Задание 1.5 Выполните проверку рассмотренного примера, измените приложение так, чтобы переменные и константы получали свои значения при запуске программы (аргументы командной строки).

Если необходимо обеспечить преобразование к меньшему типу без потери данных, всегда можно реализовать подходящую функцию. Например:

func Uint8FromInt(x int) (uint8, error) {

if 0 <= x && x <= math.MaxUint8 {

return uint8(x), nil

}

return 0, fmt.Errorf("%d за пределами диапазона uint8", x)

}

Эта функция принимает аргумент типа int и возвращает значение типа uint8 и nil, если целое число находится в заданном диапазоне, или 0 и значение ошибки в противном случае. Константа math.MaxUint8 определена в пакете math, где также имеются похожие константы для остальных встроенных числовых типов. Функция fmt.Errorf() возвращает значение ошибки, основанное на строке формата и указанном значении.

Задание 1.6 Выполните проверку функции.

К значениям одного типа могут применяться арифметические операторы – в таблице 1.3 перечислены операторы, которые могут применяться к значениям любых числовых (встроенных) типов.

Таблица 1.3  Арифметические операторы, применимые ко всем встроенным числовым типам

Оператор

Описание/результат

+x

x

-x

Изменение знака x

x++

Увеличивает x на значение нетипизированной константы 1

x--

Уменьшает x на значение нетипизированной константы 1

x += y

Увеличивает значение x на значение y

x -= y

Уменьшает значение x на значение y

x *= y

Присваивает переменной x результат умножения x на y

x /= y

Присваивает переменной x результат деления x на y. Если x и y – целые числа, остаток от деления теряется. Деление на нуль вызывает аварию (исключение)

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

const (

большоеЧисло int64 = 10000000000 // тип: int64

вещественноеЧисло = 16.0 / 9.0 // тип: float64

комплексное Число = complex(-2, 3.5) * вещественноеЧисло

// тип: complex128

логическоеЗначение = 0.0 <= вещественноеЧисло &&

вещественноеЧисло < 2.0 // тип: bool

)

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

Задание 1.7 Выведите значения констант на экран.

Рассмотрим целочисленные типы данных в Go. Язык обеспечивает как знаковую, так и беззнаковую целочисленную арифметику. Имеются знаковые целые числа четырех размеров  8, 16, 32 и 64 бита,  представленные типами int8, int16, int32 и int64, а также соответствующие беззнаковые версии uint8 , uint16, uint32 и uint64. Для большинства ситуаций достаточно использовать единственный целочисленный тип int. Переменные этого типа подходят для использования в качестве счетчиков циклов, индексов массивов и срезов и арифметических вычислений общего назначения.

Тип rune является синонимом для типа int32 и по соглашению указывает, что данное значение является символом Unicode. Эти два имени могут использоваться взаимозаменяемо. Тип byte является синонимом для типа uint8 и подчеркивает, что это значение является фрагментом неформатированных данных, а не малым числом.

Имена и диапазоны значений представлены в таблице 1.4.

Таблица 1.4  Целочисленные типы и диапазоны представляемых значений

Тип

Диапазон представляемых значений

byte

Синоним типа uint8

int

Диапазон int32 или int64, в зависимости от реализации

int8

[-128, 127]

int16

[-32768, 32767]

int32

[-2147483648, 2147483647]

int64

[-9223372036854775808, 9223372036854775807]

rune

Синоним типа int32

uint

Диапазон uint32 или uint64, в зависимости от реализации

uint8

[0, 255]

uint16

[0, 65535]

uint32

[0, 4294967295]

uint64

[0, 18446744073709551615]

uintptr

Беззнаковое целое, пригодное для хранения значения указателя

В таблице 1.5 представлены арифметические операторы, применяющиеся только к встроенным целочисленным типам.

Таблица 1.5  Арифметические операторы, применимые только к встроенным целочисленным типам

Оператор

Описание/результат

^x

Поразрядное дополнение значения x

x %= y

Присваивает переменной x остаток от деления x на y; деление на нуль вызывает аварию

x &= y

Присваивает переменной x результат поразрядной операции «И» над значениями x и y

x |= y

Присваивает переменной x результат поразрядной операции «ИЛИ» над значениями x и y

x ^= y

Присваивает переменной x результат поразрядной операции «исключающее ИЛИ» над значениями x и y

x &^= y

Присваивает переменной x результат поразрядной операции «И-НЕ» над значениями x и y

x >>= u

Присваивает переменной x результат поразрядного сдвига вправо значения x на беззнаковое целое число u бит

x <<= u

Присваивает переменной x результат поразрядного сдвига влево значения x на беззнаковое целое число u бит

x % y

Остаток от деления x на y; деление на нуль вызывает аварию

x & y

Операция «поразрядное И»

x | y

Операция «поразрядное ИЛИ»

x ^ y

Операция «поразрядное исключающее ИЛИ»

x &^ y

Операция «поразрядное И-НЕ»

x << u

Поразрядный сдвиг влево значения x на беззнаковое целое число u бит

x >> u

Поразрядный сдвиг вправо значения x на беззнаковое целое число u бит

Если результат арифметической операции, как знаковой, так и беззнаковой, имеет больше битов, чем может быть представлено типом результата, мы говорим о переполнении (overflow). При этом старшие биты, которые не помещаются в результате, отбрасываются. Если исходное число имеет знаковый тип, результат может быть отрицательным, если левый бит равен 1, как показано в следующем примере с int8 :

var u uint8 = 255

fmt.Println(u, u+1, u*u) // "255 0 1"

var i int8 = 127

fmt.Println(i, i+1, i*i) // "127 -128 1"