Golang: основы для начинающих

Golang, или Go — язык программирования, начало которого было положено в 2007 году сотрудниками компании Google: Робертом Гризмером, Робом Пайком и Кеном Томпсоном.

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

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

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

Размер программ на Go начинается с 3 строк и может достигать нескольких миллионов, записанных в один или несколько файлов с расширением .go. Современные текстовые редакторы, например, vim, поддерживают его синтаксис.

Настройка окружения

Для начала скачаем 64-битную версию Go c официального сайта. В зависимости от используемой операционной системы выполняем следующие действия.

UNIX / Linux / MacOS X / FreeBSD

Извлекаем скачанный архив в папку /usr/local/go. Например:

tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz

Добавляем папку /usr/local/go/bin в переменную окружения PATH:

export PATH=$PATH:/usr/local/go/bin

Windows

Используем MSI файл и следуем инструкциям. По умолчанию инструменты Go размещаются в папке С:\Go. При установке папка C :\Go\bin автоматически добавится в системную переменную PATH.

Чтобы изменения вступили в силу, перезапустим все открытые окна эмуляторов терминала.

Проверяем корректность установки, создав и выполнив файл C:\Projects\Go\test.go:

package main

import "fmt"

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

Выполним этот код и получим следующий результат:

Синтаксис

Пакеты

Каждая программа на языке Go состоит из пакетов (packages). Пакет main — главный, с него начинается выполнение программы. В приведённом выше примере импортируется пакет fmt.

Импорт

Импорт пакетов можно описать двумя способами.

Так:

import "fmt"
import "math"

или так:

import(
    "fmt"
    "math"
)

Функции

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

func function_name( [список параметров] ) [возвращаемые типы данных] {
    тело функции
}

Количество и тип входных аргументов может быть любым. Для примера опишем функцию add с двумя входными параметрами формата int:

package main

import "fmt"

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

func main() {
    fmt.Println("Сумма равна ", add(10, 19))
}

Выполним этот код и получим следующий результат:

Переменные

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

var [перечень переменных] [тип данных];

С помощью оператора var определяем перечень переменных, причём тип данных указываем в конце выражения.

Объявление возможно как на уровне пакета, так и на уровне функции. Рассмотрим пример:

package main

import "fmt"

var node, golang, angular bool

func main() {
    var x int
    fmt.Println(x, node, golang, angular)
}

Выполним этот код и получим следующий результат:

Оператор цикла

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

  1. Инициализация. Выполняется перед первой итерацией.
  2. Условие. Вычисляется перед каждой итерацией.
  3. Инкремент. Выполняется после каждой итерации.

Общая форма цикла выглядит так:

for [условие | (инициализация; условие; инкремент) | диапазон] {
    [тело цикла]
}

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

Цикл останавливает свою работу, когда условие принимает значение false.

Примечание В отличие от таких языков, как C, Java и JavaScript, перечисленные выражения цикла не выделяются скобками. В данном случае обязательны лишь фигурные скобки, обрамляющие тело цикла.

Рассмотрим пример программы:

package main

import "fmt"

func main() {
    sum := 0
    for i := 0; i < 8; i++ {
        sum += i
    }
    fmt.Println("Сумма равна ", sum)
}

Выполним этот код и получим следующий результат:

Условный оператор

Форма определения условного оператора в Go выглядит следующим образом:

if [условие] {
   ...
}

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

Условие описывается значением, переменной или выражением. Например:

  • true — выполняется всегда;
  • a < 10 — выполняется, когда a меньше 10;
  • (a < b) || (a < c) — выполняется, когда a меньше b или a меньше c;
  • (a < b) && (a < c) — выполняется, когда a меньше b и a меньше c.

Рассмотрим пример программы:

package main

import (
    "fmt"
)

func main() {
    if true {
        fmt.Println("Это выражение выполнится всегда")
    }

    if false {
        fmt.Println("Это выражение не выполнится никогда")
    }
}

Выполним этот код и получим следующий результат:

Массивы

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

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

var наименование_переменной [размер] тип_переменной

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

var balance [10] float32

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

var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}

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

Рассмотрим пример программы:

package main

import "fmt"

func main() {
    var a [2]string
    a[0] = "Привет"
    a[1] = "Tproger"
    fmt.Println(a[0], a[1])
    fmt.Println(a)

    primes := [6]int{2, 3, 5, 7, 11, 13}
    fmt.Println(primes)
}

Выполним этот код и получим следующий результат:

Срезы

Срезы (Slices) в Go — абстракция над массивами. Хотя встроенных способов увеличить размер массива динамически или сделать вложенный массив в Go нет, срезы убирают это ограничение. Они предоставляют полезные функции и широко используются программистами.

Объявить срез можно как массив, но без указания размера или с помощью функции make:

var numbers []int /* срез неопределённого размера */

/* numbers = []int{0,0,0,0,0} */

numbers = make([]int,5,5) /* срез длиной и ёмкостью равной 5 */

Размер массива фиксирован, а у среза изменяемый. По сути, срез — более общий вид массива.

Тип []T — срез с элементами типа T.

a[0:5] — срез 5 элементов массива a.

Рассмотрим пример программы:

package main

import "fmt"

func main() {
    primes := [6]int{2, 3, 5, 7, 11, 13}
    fmt.Println(primes)

    var s []int = primes[1:4]
    fmt.Println(s)
}

Выполним этот код и получим следующий результат:

Структуры

Структура (structure) — пользовательский тип данных, который кроме прочего комбинирует элементы разных типов. Чтобы объявить структуру, используем выражения type и struct.

Struct определяет тип данных, которому соответствует два и более элементов.

Type связывает заданное имя с описанием структуры.

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

type struct_variable_type struct {
   member definition;
   member definition;
   ...
   member definition;
}

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

variable_name := structure_variable_type {значение1, значение2...значениеN}

Чтобы получить доступ к элементам структуры, используем оператор доступа к элементу. Рассмотрим на примере:

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    v.X = 4
    fmt.Println(v.X)
}

Выполним этот код и получим следующий результат:

Почему именно Golang?

Концепция языка Golang разработана на основе опыта решения повседневных задач и не преследует цель сделать прорыв в программировании. Кроме того, Go не реализует ряд функций, которые делают другие языки (C++, Java и Python) настолько мощными. Но есть три причины, чтобы задуматься об использовании этого языка.

Читабельность

Как только привык к синтаксису Go, прочесть чужой код — тривиальная задача.

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

Скорость

За короткий промежуток времени можно написать быструю программу.

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

Меньше ошибок

Большинство ошибок возникают в непроверенном или сложном коде.

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

Заключение

Если хотите погрузиться глубже в изучение, посмотрите нашу подборку бесплатных книг по знакомству с Go, а главное — начните создавать маленькие программы, чтобы на практике понять тонкости языка. Удачи!

 

Перевод статьи «Basics of Golang [For Beginners]», с использованием «Golang Beginner Tutorial»