cpp

Структура программы

Компилировать и запускать программу на выполнение мы научились, теперь можно приступать к изучению синтаксиса языка Go. Как вы уже знаете, программа состоит из инструкций, расположенных в текстовом файле, сохраненном в кодировке UTF-8. Каждая инструкция располагается на отдельной строке. Давайте рассмотрим инструкции из листинга 1.1.

Первая инструкция с помощью ключевого слова package объявляет пакет с названием main:

package main

Весь код в языке Go всегда расположен внутри какого-либо пакета. Пакет, в котором расположена точка входа в приложение, должен иметь название main. Именно так мы и назвали наш пакет. Точкой входа в наше приложение является функция main(), инструкции внутри блока которой будут выполнены после запуска программы. Внутри функции main() мы вызываем функцию Println(), которая расположена в пакете с названием fmt, входящем в состав стандартной библиотеки языка Go. Прежде чем использовать функцию Println() нужно подключить пакет fmt к нашей программе. Подключение выполняется с помощью ключевого слова import, после которого внутри кавычек указывается название подключаемого пакета:

import "fmt"

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

.\main.go:3:8: imported and not used: "fmt"

Аналогичная ситуация возникнет при наличии неиспользуемых переменных.

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

<Название пакета>.<Идентификатор>

Вначале указывается название пакета без кавычек, затем добавляется оператор точка и после указывается идентификатор, к которому мы обращаемся:

fmt.Println("Hello, world!")

Самой главной функцией в программе является функция main(). Именно функция с названием main() будет автоматически вызываться при запуске программы. Объявление функции выполняется с помощью ключевого слова func, после которого указывается название функции. Если функция не принимает никаких параметров, то после названия функции добавляются пустые круглые скобки. В противном случае внутри круглых скобок указываются названия переменных и их тип данных. После закрывающей круглой скобки можно указать тип возвращаемого функцией значения. Если функция ничего не возвращает, то ничего указывать не нужно. Далее внутри фигурных скобок добавляются инструкции, которые будут выполнены при вызове функции:

func <Название>([<Параметры>]) [<Возвращаемое значение>] {
   <Тело функции>
}

Пример объявления функции main():

func main() {
}

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

func main() 
{
}

В языке Go в этом случае мы получим ошибку при компиляции:

.\main.go:5:6: missing function body
.\main.go:6:1: syntax error: unexpected semicolon or newline before {

Итак, функция — это именованный фрагмент кода, который можно вызвать сколько угодно раз. Фрагмент кода ограничен фигурными скобками, которые определяют область видимости идентификаторов. Например, если внутри блока объявить переменную, то она будет видна только внутри блока. В нашем случае функция main() вызывается автоматически один раз при запуске программы. Внутри функции main() мы вызываем функцию Println() из пакета fmt:

fmt.Println("Hello, world!")

При вызове функции указывается ее название, после которого внутри круглых скобок передаются значения через запятую. В нашем примере мы передаем одно значение, которое является строкой. Строка указывается внутри кавычек. Функция Println() выводит указанные значения в поток вывода и автоматически вставляет символ перевода строки. Поток вывода в нашем случае связан с окном консоли, поэтому мы увидим результат в командной строке.

Функцию Println() мы можем вызывать сколько угодно раз:

func main() {
   fmt.Println("Строка 1")
   fmt.Println("Строка 2")
   fmt.Println("Строка 3")
}

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

C:\book\test>go run main.go
Строка 1
Строка 2
Строка 3

В результате мы получили три строки, причем на русском языке без проблем с кодировками. Преобразование кодировок при выводе данных производится автоматически. Вы же помните, что наш файл сохранен в кодировке UTF-8? А консоль использует по умолчанию кодировку windows-866. Давайте в этом убедимся:

C:\book\test>chcp
Текущая кодовая страница: 866

Давайте посмотрим на формат функции Println():

Println(a ...interface{}) (n int, err error)

Итак, функция принимает один параметр, который имеет тип interface{}. Такой тип называется пустым интерфейсом. Пустой интерфейс реализуют данные любого типа, поэтому в функцию мы можем передать любые данные, например, целое число:

func main() {
   fmt.Println(10)
}

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

C:\book\test>go run main.go
10

Троеточие, указанное перед типом, означает, что функция может принимать произвольное количество значений. Значения указываются через запятую:

func main() {
   fmt.Println(true, 10, 14.5, "строка")
}

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

C:\book\test>go run main.go
true 10 14.5 строка

Обратите внимание: при выводе между значениями добавляется пробел.

Как уже говорилось, функция может возвращать значение в точку вызова. Функция Println() возвращает сразу два значения. Первое значение содержит количество байт, записанных в поток. Через второе значение можно получить сообщение об ошибке. Если ошибка не возникла, то значением будет nil (нулевой указатель). Пример получения значений:

func main() {
   n, err := fmt.Println("строка")
   fmt.Println(n, err)
}

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

C:\book\test>go run main.go
строка
13 <nil>

Обратите внимание на объявление сразу двух переменных. Вначале через запятую указываются названия переменных. Затем идет оператор :=. После оператора через запятую указываются присваиваемые значения. В нашем случае вызывается функция Println(), которая возвращает эти два значения. Тип данных переменных будет выведен компилятором из контекста. Так переменная n будет иметь тип int (целое число), а переменная err — тип error. Язык Go является строго типизированным, поэтому типы имеют важное значение. Если попытаться присвоить переменной данные другого типа, чем при объявлении, по при компиляции будет выведено сообщение об ошибке. Это позволяет избежать множества ошибок еще на этапе компиляции программы.

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

func main() {
   _, err := fmt.Println("строка")
   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println("Операция успешно выполнена")
   }
}

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

C:\book\test>go run main.go
строка
Операция успешно выполнена

Итак, в этом примере мы проигнорировали первое возвращаемое значение и получили второе значение, сохранив его в переменной err. Если возникла ошибка, то переменная err будет содержать объект ошибки. В противном случае переменная будет содержать значение nil. Проверить условие можно с помощью оператора ветвления if, который имеет следующий основной формат:

if <Условие> {
   <Блок, выполняемый, если условие возвращает Истину>
} else {
   <Блок, выполняемый, если условие возвращает Ложь>
}

Вначале проверяется условие, указанное после ключевого слова if. Если условие возвращает значение true (Истина), то выполняются инструкции из первого блока, а инструкции из второго блока пропускаются. Если условие возвращает значение false (Ложь), то инструкции из первого блока пропускаются и выполняются инструкции из второго блока. В нашем примере мы проверяем условие на неравенство переменной err значению nil (err != nil). Если переменная не содержит значение nil, значит возникла ошибка, сообщение о которой мы выводим внутри первого блока. Если переменная содержит значение nil, то операция выполнена успешно и мы выводим сообщение об этом внутри второго блока.

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

Стиль кодирования языка Go указывает, что в качестве отступа нужно использовать табуляцию. На мой взгляд это неправильно. Проблема заключается в том, что размер табуляции в разных системах может быть разным. В результате вид программы будет отличаться, что очень неудобно. Достаточно посмотреть как выглядит код программы, размещенный на сайтах. Размер табуляции на веб-страницах гораздо больше, чем три или четыре пробела. В результате код просто разъезжается в разные стороны и становится абсолютно нечитабельным. К сожалению, специализированные редакторы, например, Visual Studio Code с расширением Go, автоматически заменяют пробелы символом табуляции. Мне это увы не подходит.

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

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

fmt.Println(
   "строка 1",
   "строка 2")

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

func main() {
   fmt.Println("строка 1");
   fmt.Println("строка 2");
}

Точку с запятой нужно указывать обязательно, если на одной строке расположено несколько инструкций:

func main() {
   fmt.Println("строка 1"); fmt.Println("строка 2")
}

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

;

Учебник Go (Golang)
Учебник Go (Golang) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов

cpp