Знакомство с Go: что это за язык и стоит ли его изучать?

Андрій Денисенко

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

Go разрабатывался в компании Google с 2007-го года и уже в 2009-м году был представлен официально. Это выразительный, компактный язык с понятным синтаксисом, что упрощает создание программ.

Благодаря механизмам параллелизма этот язык позволяет пользоваться преимуществами многоядерных и сетевых компьютеров.

Несмотря на то, что это компилируемый язык со статической типизацией, с ним так же легко работать, как и с интерпретируемым языком с динамической типизацией. Go поддерживают ОС Linux, Windows, macOS, OpenBSD, DragonFly BSD, FreeBSD, NetBSD, Solaris.

Синтаксис Go

Синтаксис Go напоминает синтаксис C. Некоторые элементы заимствованы из языка Оберон и скриптовых языков. Это регистрозависимый язык. В идентификаторах и строках полностью поддерживается Юникод.

Чтобы получить базовое представление о синтаксисе Go, разберем простую программу:

package main

import "fmt"

// The entry point
func main() {
    fmt.Println("Привет, Go!")
}

Вначале необходимо определить имя пакета. Это делается с помощью ключевого слова package:

package main

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

Функции, типы, переменные и константы, определенные в одном исходном файле пакета, доступны во всех остальных исходных файлах этого пакета.

Пакет main используется для создания исполняемого двоичного файла. Выполнение программы начинается с вызова функции main из этого пакета.

Один пакет можно импортировать в другой. Для этого используется ключевое слово import. За ним указывается имя импортируемого пакета в кавычках:

import "fmt"

Следующая строка содержит комментарий. В Go используются комментарии в стиле C. В этом примере видим строчный комментарий, который начинается с двух косых черт (// ...). Блочные комментарии из нескольких строк вставляются между /* и */. Компилятор воспринимает строчный комментарий и блочный комментарий из нескольких строк как перевод строки, а однострочный блочный — как пробел.

Определение функции main:

func main() {
    fmt.Println("Привет, Go!")
}

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

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

В отличие от языка C, точка с запятой в Go используется редко: в некоторых случаях в операторах if, for и switch, а также для разделения команд, помещенных в одной строке. Компилятор сам расставляет точки с запятой в конце строк, поэтому нужно запомнить, что перенос строки допустим не в любом месте, где можно использовать пробел. Например, в объявлениях функций необходимо ставить фигурную скобку после круглой, завершающей список аргументов:

func a(){
}

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

func a();
{
}

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

if condition {
    ...
};
else {
    ...
}

Код тела функции состоит из единственной строки, которая выводит строку «Привет, Go!» и переводит курсор на следующую строку:

fmt.Println("Привет, Go!")

В этой строке мы вызываем функцию Println из пакета fmt. Для этого сначала указываем имя пакета, затем через точку — имя функции, а в скобках приводим строковой аргумент в прямых двойных кавычках. Двоеточие после вызова функции не ставим, потому что его подставит компилятор.

Сохраните код из начала раздела в файле hello.go и запустите программу в командной строке или терминале: 

go run hello.go

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

Результат работы программы

Теперь расширим возможности этой маленькой программы: научим ее «обращаться» к пользователю по имени.

Ознакомьтесь с кодом:

package main

import (
  "fmt"
  "os"
)

func main() {

  var name string

  fmt.Print("Как тебя зовут? ")
  fmt.Fscan(os.Stdin, &name)
  fmt.Println("Привет,", name + "!")
}

Чтобы ввести имя пользователя с консоли, воспользуемся функцией Fscan из пакета os. Для этого в текущий код нужно добавить еще одно объявление импорта. Можно вставить еще одну строку:

import "fmt"
import "os"

Такой вид импорта называется прямым. Но рекомендуется использовать более удобный способ — групповой:

import (
    "fmt"
    "os"
)

При его использовании код выглядит понятнее и не приходится каждый раз указывать ключевое слово import.

В первой строке тела функции объявляем переменную строкового типа. Для этого используем ключевое слово var, после него через разделитель укажем имя переменной, после чего определим ее тип (тоже через разделитель):

var name string

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

var name string = "No name"

Далее выведем запрос на ввод имени:

fmt.Print("Как тебя зовут? ")

Для вывода используется команда Print, которая работает так же, как и Println, но не переводит строку. После запроса в строке оставлен пробел, чтобы отделить запрос от ввода.

Далее считаем ввод в переменную name из стандартного ввода os.Stdin:

fmt.Fscan(os.Stdin, &name)

Теперь по адресу (&) переменной name находится введенный текст.

Выведем приветствие на экран:

fmt.Println("Привет,", name + "!")

Если в функции Println указано несколько аргументов, то они выводятся через пробел, поэтому перед закрывающей кавычкой здесь пробел не ставим. Второй аргумент получаем с помощью конкатенации — «сложения» строк.

Вывод будет выглядеть так:

Результат работы программы

Пришло время подробнее рассмотреть использованные в примерах возможности языка.

Импорт в Go

В Go используется несколько типов импорта.

Типы импорта в Go
Пример Описание Использование в коде
import "fmt" Прямой импорт. В кавычках указывается путь к пакету. Для встроенных пакетов указывается только их имена. Также можно указывать пути в интернете, например: github.com/<username>/<package> fmt.Print("Go")
import (
    "fmt"
    "os"
)

 

Групповой импорт. os.Stdin
import "math/rand" Вложенный импорт. Используется, когда нужно воспользоваться только подмножеством функций пакета. rand.Int(100)
import f "fmt" Импорт с псевдонимом f.Println("Go")
import . "math" Импорт без указания имени пакета (квалификации). Используется, в основном, для тестирования публичных элементов. Может вызвать конфликт пространства имен. Sin(1.0)
import _ "math" Пустой импорт. Если пакет импортирован, но не используется, то в Go возникает ошибка. Чтобы она не возникала, используется пустой импорт. Когда потребуется воспользоваться пакетом, определение импорта можно будет заменить другим.

Типы данных в Go

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

Рассмотрим встроенные типы данных.

Числовые типы

Целые числа
Тип Описание

uint8 и byteuint16

uint32

uint64

Беззнаковые целые числа. Принимают только неотрицательные значения. 8, 16, 32 и 64 — это количество бит, которое отведено на число соответствующего типа.

int8

int16

int32 и rune

int64

Знаковые целые числа.

uint

int

uintptr

Машинно-зависимые целочисленные типы.
Вещественные числа
Тип Описание
float32 С одинарной точностью
float64 С двойной точностью

Еще существуют значения NaN (not a number) для результатов таких вычислений, как 0/0, а также положительная и отрицательная бесконечность (+∞ и −∞).

Комплексные числа
Тип Описание
complex64 Вещественная и мнимая части представлены числами с типом float32
complex128 Вещественная и мнимая части представлены числами с типом float64

Над числами в Go можно производить приведенные ниже операции.

Операции над числами в Go
+ сложение
вычитание
* умножение
/ деление
% остаток от деления

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

Строки

Строки в Go представляют собой неизменяемые последовательности символов UTF-8. Они заключаются в двойные кавычки или в обратные галочки.

В строках в двойных кавычках можно использовать управляющие символы, такие как \r, \t.

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

Строки могут быть пустыми, но пустые строки не являются нулевыми.

Для строк предусмотрена операция конкатенации, как мы уже видели во втором примере кода. Для нее используется тот же оператор, что и для сложения (+).

Чтобы узнать количество символов в строке, независимо от кодировки, используется функция RuneCountInString() из пакета UTF-8. Функция len()возвращает число байтов в строке.

Важно помнить, что строки неизменяемы, и попытка изменить строку приводит к ошибке.

Булевский тип

Это однобайтовый целочисленный тип, значения которого представляют истинность и ложность (соответственно true и false).

Для этого типа предусмотрены три оператора:

Логические операторы
&& и
|| или
! не

В Go поддерживаются также массивы, представляющие собой последовательности элементов одного типа.

Переменные и присваивание в Golang

Объявление переменной начинается с ключевого слова var, после разделителя указывается имя переменной, а за ним после разделителя — тип:

var x int32

После объявления переменных разных типов они получают нулевые значения: все числовые типы — 0, строковые — пустую строку, указатели — nil.

После объявления переменной можно присвоить ей значение. Для явного присваивания значений переменной с заданным типом используется символ =:

x = 100

Присвоить переменной значение можно и в объявлении. Инициализация переменной с указанием типа производится так:

var y string = "Hello"

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

var z = true

Локальные переменные можно объявлять и инициализировать с помощью сокращенной формы записи и оператора := :

n = 20

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

var (
    firstName string = "Luke"
    lastName string = "Skywalker"
)

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

var numbers [5]int

Константы

Константы в Go бывают типизированные и нетипизированные. Типизированные константы объявляются так же, как и переменные с инициализацией, только с использованием ключевого слова const:

const pi float64 = 3.1415

Нетипизированная константа определяется без указания типа:

const a = 1

После этого объявления значение 1 не отнесено к какому-либо типу. Это просто целочисленное значение. Оно может использоваться в операциях с целыми числами.

Управляющие конструкции в Go

Условные конструкции

Конструкция if…elseпринимает выражение, которое возвращает булевское значение. Если возвращено значение true, то выполняется блок кода в фигурных скобках, следующий за конструкцией:

if x > 0 {
    fmt.Println("x - положительное")
}

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

Если нужно, чтобы один код выполнялся при истинном значении условного выражения, а другой — при ложном, используется ключевое слово else:

if x > 0 {
    fmt.Println("x - положительное")
} else {
    fmt.Println("x - не положительное")
}

Условия можно «нанизывать»:

if x > 0 {
    fmt.Println("x - положительное")
} else if x < 0 {
    fmt.Println("x - отрицательное")
} else {
    fmt.Println("x - ноль")
}

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

switch(n) {
    case 1: 
        fmt.Println("n = 1")
    case 2: 
        fmt.Println("n = 2")
    case 3, 4: // несколько значений
        fmt.Println("n = 3 или 4")
    default: // если не совпало с указанными значениями
        fmt.Println("значение n не соответствует предусмотренным")

Циклы

В Go есть только один цикл — for.Он имеет следующую структуру:

for [инициализация;] [условие;] [приращение] {
    // действия
}

Например:

for i = 1; i < 10; i++ {
    fmt.Println(i * i)
}

В этом цикле выводятся квадраты чисел от 1 до 9. Вначале счетчик получает значение 1 и при каждой итерации оно увеличивается на единицу. Итерации прекращаются по достижении счетчиком значения 10.

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

i = 0
for{
    if i < 5 {
        continue
    } else if i > 9 {
        break
    }
    fmt.Println(i * i)
}

Этот цикл выведет квадраты чисел от 5 до 9 включительно. Пока значение счетчика будет меньше 5, ключевое слово continue не будет передавать управление строке, которая выводит значение на экран. Начиная со значения 5 значение будет выводиться, а когда счетчик получит значение 10, ключевое слово break осуществит выход из цикла.

Функции в Go

Объявление функции в Go:

func имя (параметры) (типы_возвращаемых_значений){
    операторы
}

Функция, не возвращающая значение:

func hello() {
    fmt.Println("Hello!")
}

Для возврата значения из функции используется оператор return и указывается тип возвращаемого значения:

func add (a int, b int) int {
    return a + b
}

Возвращаемое значение может быть именованным:

func add (a int, b int) (z int) {
    z = a + b
    return
}

Поскольку переменная z определена как возвращаемое значение, ее не приходится указывать после оператора return.

Функция может возвращать несколько значений:

func addmul (a, b int) (int, int) {
    c = a + b
    d = a * b
    return c, d
}

x, y = addmul(2, 5)

Эти результаты также могут быть именованными:

func addmul (a, b int) (c, d int) {
    c = a + b
    d = a * b
    return
}

Поскольку в Go не только пакеты, но и объявленные переменные обязательно должны использоваться в программе, предусмотрена псевдопеременная _. Она позволяет проигнорировать возвращаемое значение.

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

x = addmul(2, 5)

Псевдопеременная позволяет избежать ошибки:

x, _ = addmul(2, 5)

Отложенный вызов и обработка ошибок

В Golang не реализованы обработчики исключительных ситуаций. Вместо них и блоков с гарантированным завершением используется ключевое слово defer. Указанная после него функция будет выполнена по завершении функции, в которой используется эта конструкция:

func main() {
    defer deferred()
    fmt.Println("Программа запущена")
}
 
func deferred(){
    fmt.Println("Выполнение программы завершено")
}

Несмотря на то, что функция, выводящая строку «Программа запущена», находится в конце функции main, она будет вызвана первой из двух строк тела функции.

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

Выполним такую программу:

package main 

import "fmt"

func main () {
    defer bye()
    fmt.Println(div(8, 2))
    fmt.Println(div(8, 0))
}

func div (a, b float32) float32 {
    if b == 0 {
        panic("Попытка деления на ноль.")
    }
    return a/b
}

func bye () {
       fmt.Println("Пока!")
}

В результате ее выполнения в консоли будет выведено число 4, строка «Пока!» и сообщение об ошибке:

Результат работы программы

Многопоточность в Go

Поток программы создается ключевым словом go. Оно запускает функцию в новой сопрограмме. В Go такие сопрограммы называются go-процедурами. Они выполняются параллельно. При использовании многоядерных процессоров эти процедуры могут выполняться на разных ядрах, что ускоряет работу программы.

Go-процедуры экономны по сравнению с нитями. Размер их стека составляет лишь несколько килобайт, и он может изменяться в зависимости от требований приложения.

Рассмотрим простой пример использования go-процедур:

package main

import (  
    "fmt"
)

func hello() {  
    fmt.Println("Hello from goroutine")
}
func main() {  
    go hello()
    fmt.Println("Hello from main function")
}

Программа создает go-процедуру, которая может вывести в консоли приветствие Hello from goroutine, затем выводит приветствие Hello from main function. Запустим программу в консоли несколько раз:

Результат работы программы

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

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

package main

import (  
    "fmt"
)

func hello() {  
    fmt.Println("Hello from goroutine")
}
func main() {  
    go hello()
    fmt.Scanln()
    fmt.Println("Hello from main function")
}

В результате получим:

Результат работы программы

Go-процедуры обмениваются данными через каналы. Для их создания используется ключевое слово chan с указанием типа элемента. Переменная для канала, по которому передаются целые числа, определяется таким образом:

var intChannel chan int

Теперь по нему можно передавать числа с помощью оператора <- :

intChannel <- 7 // передаем данные в канал
intValue := <- intChannel // получаем данные из канала

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

Каналы бывают буферизированные и небуферизированные. Для создания небуферизированного канала используется функция make() без указания аргументов (емкости канала):

var intChannel chan int = make(chan int)

Также можно воспользоваться выводом типов:

intChannel := make(chan int)

Процедура-получатель работает только тогда, когда в канале есть данные. Когда канал пуст, ее работа блокируется. Процедура-отправитель передает данные в канал, когда он пуст. После отправки данных ее работа блокируется до получения данных из канала. Чтобы продемонстрировать работу с каналами, запустим следующий код:

package main

import "fmt"
 
func main() {
     
    intChannel := make(chan int)
    
    fmt.Println("Функция main запускает Go-процедуру.")
     
    go func(){
            fmt.Println("Go-процедура отправляет данные в канал.")
            fmt.Println("Ее работа блокируется.")
            intChannel <- 10
            fmt.Println("Данные переданы в канал.")
            fmt.Println("Go-процедура разблокирована.")
    }() // В качестве go-процедур можно использовать замыкания

    intResult := <-intChannel
    fmt.Println("Функция main получила данные из канала:", intResult)
}

Вывод программы будет выглядеть так:

Результат работы программы

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

Примеры использования

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

В первом примере будем использовать функции из нескольких модулей, условные конструкции, цикл, два вида присваивания, псевдопеременную. Код не требует отдельных пояснений — читайте комментарии:

/* Основы синтаксиса Go
на примере программы 
для угадывания числа */
// Объявление пакета
package main

// Импорт модулей, необходимых для работы программы
import (
  "fmt"
  "os"
  "math/rand"
  "time"
)

// Точка входа (отсюда начинается выполнение программы)
func main() {

  // Переменная для загаданного числа
  var secret int
  
  // Переменная для номера попытки
  var attempt int = 0
   
  // Флаг завершения игры
  var isOver bool = false
  
  // Число пользователя
  var number int = 0
  
  var win bool = false
  
  // Получим порождающий элемент с автоматическим выводом типа (:=)
  seed := time.Now().UnixNano()
  
  // Зададим порождающий элемент
  rand.Seed(seed)
  
  // Получим случайное число и присвоим его переменной явно (=)
  secret = rand.Intn(1024) + 1
  
  // Выведем приглашение
  fmt.Println("Отгадайте целое число от 1 до 1024.")
  fmt.Println("Для выхода введите 0.")
  fmt.Println()
  
  // Начнем бесконечный цикл с выходом при условии истинности isOver
  for {
  
    attempt++
    fmt.Print("Введите число: ")
    _, err := fmt.Fscan(os.Stdin, &number)
    
    // Проверим, введено ли допустимое число
    if err != nil {
      fmt.Println("Вводите только целые числа!")
      attempt--
      continue
    }
    
    // Проанализируем ввод
    if number == 0 { // Команда выхода?
      isOver = true
    } else if number == secret { // Число угадано?
      win = true
      isOver = true
    } else if number < secret { // Догадка меньше загаданного?
      fmt.Println("Маловато будет!")
    } else { // Значит, догадка больше загаданного
      fmt.Println("Многовато будет!")
    }
      
    if isOver { // Постусловие выхода
      break
    }
  } // Флаг выхода установлен в true
  
  // Выведем сообщение о результате
  if win {
    fmt.Println("Вы угадали число за", attempt, "попыток.")
  }
  
   fmt.Println("До свидания!")
}

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

Результат работы программы

Во втором примере продемонстрируем использование go-процедуры и каналов. Программа запросит, на сколько секунд запустить таймер, и будет вести обратный отсчет, каждую секунду выводя оставшееся время, пока не сработает таймер:

package main

import (
  "fmt"
  "os"
  "time"
)
 
func main() {
     
    seconds := 0
    fmt.Print("На сколько секунд запустить таймер? ")
    fmt.Fscan(os.Stdin, &seconds)
    
    counter := seconds
    
    timer := time.NewTimer(time.Duration(seconds) * time.Second)
    ticker := time.NewTicker(time.Second)
    
    fmt.Println(counter)
    
    go func(){
            for {
              select {
                case <- ticker.C:
                  counter--
                  fmt.Println(counter)
                case <- timer.C:
                  return
              }
            }
    }()
    time.Sleep(time.Duration(seconds) * time.Second)
    
    fmt.Println("Время вышло")
}

Где используется Go

  • Компания Google, в которой разработан Go, использует этот язык для своих внутренних проектов. В частности, на нем созданы Google Cloud и Kubernetes.
  • Многие сервисы Uber также написаны на Go. С развитием компании использовалось все больше ресурсов и повышалась задержка. Для повышения эффективности компания переписала на Go код, который ранее был написан на Python.
  • В видеостриминговом сервие Twitch язык Go используется для самых загруженных систем, в том числе для прямой трансляции видео и одновременного обслуживания множества чатов.
  • Облачная служба хранения данных Dropbox использует Go, чтобы эффективно управлять взаимодействием с более чем 500 миллионами пользователей.
  • Компания Dailymotion обеспечила с помощью этого языка автоматизацию API.
  • Облачный сервис электронной почты SendGrid использует Go как основной язык программирования. С его помощью отправляются подтверждения покупок, предложения, обрабатываются входящие сообщения и перенаправляются запросы клиентов.
  • Компания SoundCloud выбрала Go для проведения статического анализа в режиме реального времени и ускорения работы над приложениями.
  • Платформа блогов и публикаций Medium использует Go для обработки изображений.
  • BBC применяет Go для разработки серверной части приложений, в том числе для социальных сетей и мобильных устройств.
  • Компания Docker предпочитает этот язык благодаря возможностям, которые он дает для разработки крупномасштабных распределенных проектов, в том числе статической компиляции без зависимостей, надежной стандартной библиотеке, полнофункциональной среде разработки и возможности компоновать приложения для различных архитектур с минимальными трудностями.

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

Преимущества Go

  1. Go — быстрый язык. Go — это компилируемый язык. Написанный на нем код преобразуется в код, понятный процессору. Благодаря этому он работает быстрее, чем такие языки, как Java и Python, что повышает доступность и надежность служб.
  1. Язык Go легко освоить. Если у вас есть опыт программирования на C или Java, то вам будет легко освоить Go. Несмотря на некоторые различия, в Go используется же самый процедурный подход, и вам не придется тратить много времени на знакомство с ним.
  2. Go экономно использует память. Go-процедуры — это функции, которые выполняются одновременно и независимо друг от друга. Одна процедура занимает всего два килобайта памяти, что очень удобно, когда необходимо одновременно выполнять очень много процессов. Эти процедуры не являются блокирующими, как нити в Java. В них скомбинирован асинхронный подход, как в JavaScript, и традиционная многопоточность, как в Java. Но нити занимают большие объемы памяти, в то время как можно запустить миллионы компактных go-процедур без сбоев в работе системы.
  3. Статическая типизация. Благодаря статической типизации в Go сводится к минимуму риск ошибок, которые допускаются по невнимательности. Go выдаст ошибку, если переменной попытаются присвоить значение не того типа, который ей назначен. Это упрощает и ускоряет процесс разработки.

Недостатки Go

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

  1. Требует много времени. Программисту может понадобиться написать десятки строк кода, чтобы реализовать ту же функцию, которую на Python можно уместить в паре строк. Это замедляет процесс разработки программного обеспечения.
  1. Это молодой язык. Программисты, которые только начинают осваивать Go, столкнутся с проблемами работы с существующими библиотеками, особенно при взаимодействии с другими платформами. Для связывания нескольких программ потребуется писать лишний код.
  1. Go не поддерживает обобщенные функции. Обобщенные функции — это коллекция различных функций с одним и тем же именем, но с неопределенными типами входных данных на момент компиляции. Без поддержки таких функций программистам потребуется создавать множество функций, которые принимают разные параметры. Из-за этого ограничивается возможность повторного использования кода и снижается эффективность разработки.

Резюме

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

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

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

Тем не менее, Go популярен в таких сферах, как бэкенд-разработка, веб-разработка, базы данных, финансовые услуги, медиа, а чаще всего он применяется в технологическом секторе. Этот язык продолжает развиваться, и ожидается выпуск его второй версии. К тому же, он прост в изучении. Поэтому знакомство с ним не займет много времени и будет полезным. Удачи!

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

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

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023