Вы находитесь на странице: 1из 7

Go

[править | править код]
Материал из Википедии — свободной энциклопедии
Текущая версия страницы пока не проверялась опытными участниками и может значительно отличаться
от версии, проверенной 3 сентября 2019; проверки требует 31 правка.

Перейти к навигацииПерейти к поиску


У этого термина существуют и другие значения, см. Го (значения).
Не следует путать с Go!.

Go

Класс языка многопоточный, императивный, структурирова


нный

Тип компилируемый
исполнения

Появился в 10 ноября 2009

Автор Роберт Гризмер, Роб Пайк и Кен Томпсон

Разработчик Google, Роб Пайк, Кен Томпсон и The Go


Authors[d]

Расширение  .go

файлов

Выпуск 1.14.1 ( 10 марта 2020)

Система строгая, статическая, с выводом типов


типов

Испытал Си[1], Python, Оберон-2, Limbo, Active
влияние Oberon, теория взаимодействия
последовательных
процессов, Паскаль[1], Оберон[1], Smalltalk[2], New
squeak[d][3], Модула-2[3], Alef[d], APL, BCPL, Моду
ла и Оккам
Лицензия BSD

Сайт golang.org

ОС DragonFly
BSD, FreeBSD, Linux, macOS, NetBSD, OpenBS
D, Plan 9, Solaris и Microsoft Windows

Go (часто также Golang) — компилируемый многопоточный язык программирования,


разработанный внутри компании Google[4]. Разработка Go началась в сентябре 2007 года, его
непосредственным проектированием занимались Роберт Гризмер, Роб Пайк и Кен Томпсон[5],
занимавшиеся до этого проектом разработки операционной системы Inferno. Официально
язык был представлен в ноябре 2009 года. На данный момент поддержка официального
компилятора, разрабатываемого создателями языка, осуществляется для операционных
систем FreeBSD, OpenBSD, Linux, macOS, Windows, DragonFly BSD, Plan
9, Solaris, Android, AIX.[6]. Также Go поддерживается набором компиляторов gcc, существует
несколько независимых реализаций. Ведётся разработка второй версии языка.

Содержание

 1Название
 2Назначение, идеология
 3Основные возможности языка
 4Синтаксис
o 4.1Алфавит
o 4.2Пакеты
o 4.3Модули
o 4.4Комментарии и точки с запятой
o 4.5Встроенные типы данных
 4.5.1Целые числа
 4.5.2Числа с плавающей запятой
 4.5.3Числовые типы с неограниченной точностью
 4.5.4Комплексные числа
 4.5.5Логические значения
 4.5.6Строки
o 4.6Объявление типов
o 4.7Объявление переменных
o 4.8Автоматический вывод типов
o 4.9Присваивания
o 4.10Аргументы функций и методов
o 4.11Функции могут возвращать несколько значений
o 4.12Псевдопеременная «_»
o 4.13Механизм отложенного вызова defer
o 4.14Условия циклов и ветвлений
o 4.15Циклы
o 4.16Оператор множественного выбора.
 5Особенности архитектуры
o 5.1Обработка ошибок и исключительных ситуаций
o 5.2Многопоточность
o 5.3Объектно-ориентированное программирование
o 5.4Рефлексия
o 5.5Низкоуровневое программирование
o 5.6Интерфейс с кодом на других языках
o 5.7Интерфейс пользователя
 6Критика
o 6.1Отсутствие возможностей
o 6.2Архитектура
o 6.3«Подводные камни» (неудачная реализация некоторых средств)
o 6.4Другие особенности
 7Распространение и перспективы
 8Версии
o 8.1Нумерация и принципы совместимости версий
o 8.2Go 1
o 8.3Go 2.0
 9Реализации
 10Средства разработки
 11Примеры
 12Примечания
 13Пояснения
 14Литература
 15Ссылки

Название[править | править код]
Название языка, выбранное компанией Google, практически совпадает с названием языка
программирования Go!, созданного Ф. Джи. МакКейбом и К. Л. Кларком в 2003 году[7].
Обсуждение названия ведётся на странице, посвящённой Go[7].
На домашней странице языка и вообще в Интернет-публикациях часто используется
альтернативное название — «golang».

Назначение, идеология[править | править код]


Язык Go разрабатывался как язык программирования для создания высокоэффективных
программ, работающих на современных распределённых системах и многоядерных
процессорах. Он может рассматриваться как попытка создать замену языкам Си и C++ с
учётом изменившихся компьютерных технологий и накопленного опыта разработки крупных
систем[8]. По словам Роба Пайка[8], «Go был разработан для решения реальных проблем,
возникающих при разработке программного обеспечения в Google». В качестве основных
таких проблем он называет:

 медленную сборку программ;


 неконтролируемые зависимости;
 использование разными программистами разных подмножеств языка;
 затруднения с пониманием программ, вызванные неудобочитаемостью кода, плохим
документированием и так далее;
 дублирование разработок;
 высокую стоимость обновлений;
 несинхронные обновления при дублировании кода;
 сложность разработки инструментария;
 проблемы межъязыкового взаимодействия.
Основными требованиями к языку стали[9]:

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


повторяющих функциональность друг друга.
 Простая и регулярная грамматика. Минимум ключевых слов, простая, легко
разбираемая грамматическая структура, легко читаемый код.
 Простая работа с типами. Типизация должна обеспечивать безопасность, но не
превращаться в бюрократию, лишь увеличивающую код. Отказ от иерархии типов, но с
сохранением объектно-ориентированных возможностей.
 Отсутствие неявных преобразований.
 Сборка мусора.
 Встроенные средства распараллеливания, простые и эффективные.
 Поддержка строк, ассоциативных массивов и коммуникационных каналов.
 Чёткое разделение интерфейса и реализации.
 Эффективная система пакетов с явным указанием зависимостей, обеспечивающая
быструю сборку.
Go создавался в расчёте на то, что программы на нём будут транслироваться в объектный
код и исполняться непосредственно, не требуя виртуальной машины, поэтому одним из
критериев выбора архитектурных решений была возможность обеспечить быструю
компиляцию в эффективный объектный код и отсутствие чрезмерных требований к
динамической поддержке.
В результате получился язык, «который не стал прорывом, но тем не менее явился отличным
инструментом для разработки крупных программных проектов»[8].
Хотя для Go доступен и интерпретатор, практически в нём нет большой потребности, так как
скорость компиляции достаточно высока для обеспечения интерактивной разработки.

Основные возможности языка[править | править код]


Основные возможности языка Go[5]:

 Go — язык со строгой статической типизацией. Доступен автоматический вывод типов,


для пользовательских типов — «утиная типизация».
 Полноценная поддержка указателей, но без возможности применять к ним
арифметические операции, в отличие от C/C++/D.
 Строковый тип со встроенной поддержкой юникода.
 Использование динамических массивов, хеш-таблиц (словарей), срезов (слайсов),
вариант цикла для обхода коллекции.
 Средства функционального программирования: неименованные функции, замыкания,
передача функций в параметрах и возврат функциональных значений.
 Автоматическое управление памятью со сборщиком мусора.
 Средства объектно-ориентированного программирования, но без поддержки
наследования реализации (наследуются только интерфейсы). По большому счёту, Go
является процедурным языком с поддержкой интерфейсов.
 Средства параллельного программирования: встроенные в язык потоки (go routines),
взаимодействие потоков через каналы и другие средства организации многопоточных
программ.
 Достаточно лаконичный и простой синтаксис, основанный на Си, но существенно
доработанный, с большим количеством синтаксического сахара.
Go не содержит целого ряда популярных синтаксических средств, доступных в других
современных языках прикладного программирования. Во многих случаях это вызвано
сознательным решением разработчиков. Краткие обоснования выбранных проектных
решений можно найти в «Часто задаваемых вопросах»[5] по языку, более подробные — в
опубликованных на сайте языка статьях и обсуждениях, рассматривающих различные
варианты дизайна. В частности:

 Структурная запись обработчиков исключений сочтена провоцирующей на пропуск


ошибок или неадекватную их обработку. К тому же поддержка исключений серьёзно
усложняется в приложениях с параллельно работающими частями. Вместо неё
предлагается проверка кодов возврата с использованием многозначных функций и
специального интерфейса error, а также применение отложенных (deferred) функций для
перехвата исключительных ситуаций.
 Наследование реализации, как считают авторы, приводит к созданию кода с неявными
зависимостями, избыточно сложного в поддержке. Аналогичные возможности, но без
свойственных наследованию нежелательных эффектов, обеспечиваются поддержкой
вложения типов и свободно определяемыми интерфейсами.
 Обобщённое программирование. Авторы воздержались от его включения в первую
версию языка, поскольку, по их словам[5], предоставляемые им возможности не окупают
требуемого усложнения компилятора и runtime-библиотек, а уже имеющиеся в языке
средства (пустые интерфейсы, «утиная типизация» и рефлексия) позволяют создавать
обобщённый код без специальных синтаксических механизмов. Тем не менее,
обсуждается вопрос о включении таких средств в проектируемую вторую версию языка[⇨].
 Использование утверждений (assertion) было сочтено ненужным.
 Переопределение методов и функций было исключено из соображений надёжности и
эффективности компиляции: требование различного именования всех методов на одном
уровне видимости устраняет необходимость сопоставлять списки параметров при
компиляции вызовов функций и методов и исключает ошибочный вызов другого
одноимённого метода; при этом сама возможность переопределения есть не более
чем синтаксический сахар.
 Ряд операций над массивами и срезами (например, вставка элемента в середину) не
включен в язык, поскольку они достаточно затратны. Возможность их выполнения одной
простой командой провоцировала бы программиста на создание неэффективного кода,
отсутствие таких команд в языке, напротив, является стимулом для рассмотрения
альтернативных решений.
 Поддержка отрицательных индексов,[10] доступная в ряде популярных языков, может
стать причиной труднообнаруживаемых ошибок: появление отрицательного индекса из-за
ошибки в коде вместо того, чтобы привести к фатальному сбою, вызовет внешне
корректное обращение не к тем элементам массива, что проявится только в неверных
результатах и может быть обнаружено далеко не сразу.
 Принцип «любое выражение возвращает значение» провоцирует программиста на
создание сложных, трудно воспринимаемых и чреватых неочевидными ошибками
выражений (вроде копирования строки на Си командой из трёх слов:  while (*ptr1++ =
*ptr2++); ). При этом современные технологии оптимизации обеспечат одинаковый
объектный код и для экстремально сокращённого выражения, и для аналогичного ему
фрагмента, написанного безо всяких ухищрений.

Синтаксис[править | править код]
Синтаксис языка Go схож с синтаксисом языка Си, с отдельными элементами,
заимствованными из Оберона и скриптовых языков.
Алфавит[править | править код]
Go — регистрозависимый язык с полной поддержкой Юникода в строках и идентификаторах.
Идентификатор традиционно может быть любой непустой последовательностью,
включающей буквы, цифры и знак подчёркивания, начинающийся с буквы и не совпадающий
ни с одним из ключевых слов языка Go. При этом под «буквами» понимаются все символы
Юникода, относящиеся к категориям «Lu» (буквы верхнего регистра), «Ll» (буквы нижнего
регистра), «Lt» (заглавные буквы), «Lm» (буквы-модификаторы) или «Lo» (прочие буквы), под
«цифрами» — все символы из категории «Nd» (числа, десятичные цифры). Таким образом,
ничто не мешает использовать в идентификаторах, например, кириллицу.
Идентификаторы, различающиеся только регистром букв, являются различными. В языке
существует ряд соглашений об использовании заглавных и строчных букв. В частности, в
именах пакетов используются только строчные буквы. Все ключевые слова Go пишутся в
нижнем регистре.
В строковых литералах могут использоваться все символы Юникода без ограничений. Строки
представляются как последовательности символов в кодировке UTF-8.
Пакеты[править | править код]
Любая программа на Go включает один или несколько пакетов. Пакет, к которому относится
файл исходного кода, задаётся описанием package в начале файла. Имена пакетов имеют те
же ограничения, что и идентификаторы, но могут содержать буквы только нижнего регистра.
Система пакетов go-среды имеет древовидную структуру, аналогичную дереву каталогов.
Любые глобальные объекты (переменные, типы, интерфейсы, функции, методы, элементы
структур и интерфейсов) доступны без ограничений в пакете, в котором они объявлены.
Глобальные объекты, имена которых начинаются на заглавную букву, являются
экспортируемыми.
Для использования в файле кода Go объектов, экспортированных другим пакетом, пакет
должен быть импортирован, для чего применяется конструкция  import .

package main
/* Импорт */
import (
"fmt" // Стандартный пакет для форматированного вывода
"database/sql" // Импорт вложенного пакета
w "os" // Импорт с псевдонимом
. "math" // Импорт без квалификации при использовании
_ "gopkg.in/goracle.v2" // Пакет не имеет явных обращений в коде
)

func main() {
for _, arg := range w.Args { // Обращение к массиву Args, объявленному в
пакете "os", через псевдоним
fmt.Println(arg) // Обращение к функции Println(), объявленной в
пакете "fmt", с именем пакета
}
db *sql.DB = sql.Open(driver, dataSource) // Имена из вложенного пакета
квалифицируются
// только именем самого пакета
(sql)
x := Sin(1.0) // вызов math.Sin() - квалификация именем пакета math не
нужна,
// так как он импортирован без имени
// Обращений к пакету "goracle.v2" в коде нет, но он будет импортирован.
}

В ней перечисляются пути к импортируемым пакетам от каталога src в дереве исходных


текстов, положение которого задаётся переменной среды  GOPATH , а для стандартных пакетов
достаточно указать имя. Перед строкой, идентифицирующей пакет, может быть указан
псевдоним, тогда он будет использоваться в коде вместо имени пакета. Импортированные
объекты доступны в импортирующем их файле с полной квалификацией вида
« пакет.Объект ». Если при импорте пакета вместо псевдонима указывается точка, то все
экспортируемые им имена будут доступны без квалификации. Эта возможность используется
некоторыми системными утилитами, однако её применение программистом нежелательно,
так как явная квалификация обеспечивает защиту от коллизий имён и «незаметного»
изменения поведения кода. Невозможно импортировать без квалификации два пакета,
экспортирующих одно и то же имя.
Использование импортируемых пакетов в Go контролируется строже, чем в большинстве
языков. Если пакет импортирован, то в коде должно использоваться хотя бы одно
экспортируемое этим пакетом имя. Компилятор Go считает импорт неиспользуемого пакета
ошибкой; такое решение вынуждает разработчика постоянно поддерживать актуальность
списков импорта. В некоторых случаях это ограничение неудобно, например, когда пакет
содержит код, используемый посредством интроспекции, но не вызываемый напрямую:
импорт такого пакета не будет разрешён компилятором, хотя в действительности он
необходим. Для таких случаев предусмотрен анонимный импорт: в качестве псевдонима
указывается « _ » (одиночный знак подчёркивания); пакет, импортированный таким образом,
не может быть использован явно, но будет откомпилирован и включён в состав программы.
Исполняемая программа на Go обязательно содержит пакет с именем main, в котором
обязательно должна быть функция  main()  без параметров и возвращаемого значения.
Функция  main.main()  является «телом программы» — её код запускается, когда программа
стартует. Любой пакет может содержать функцию  init()  — она будет запущена при
загрузке программы перед началом её исполнения, до вызова любой функции в данном
пакете и в любом пакете, импортирующем данный. Инициализация пакета main всегда
происходит последней, и все инициализации выполняются до начала исполнения
функции  main.main() .

Вам также может понравиться