Почему мне нравится Golang

Почему мне нравится Golang

Practical.DEV

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

Впервые я приметил его около января 2016 года. У него было относительно небольшое, но воодушевленное сообщество здесь, в Израиле. В то время я не придавал ему большого значения, я оттачивал свои навыки программирования, а Golang был просто инструментом, который я использовал для выполнения задачи. Даже год назад использовать Go было удобно. Как только я получил общее представление о языке, процесс программирования упростился для меня.

Я написал важный фрагмент кода для Visualead, компании, в которой я работаю. И он не подвел нас, все еще работая в продакшене год спустя без всякого обслуживания.

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

Окружение GOPATH

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

Установите каталог GOPATH в любом месте на вашем компьютере вместе с подкаталогами bin, src и pkg и вы сразу готовы начать писать.

// Так выглядит структура каталогов:
go
- bin
- pkg
- src

В моем домашнем каталоге я создаю новый каталог для каждого языка программирования, на котором пишу. Домашний каталог заполнен такими папками:

chef
cpp
elixir
elm
go
javascript
meteor
ocaml
php
python
scala

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

Приложение Golang

Хотите создать новое приложение? Легко.

Создайте новый каталог в $GOPATH/src, в нем создайте файл file.go, вызовите пакет main, добавьте функцию func main() {} и все. С этого момента все побрякушки Go доступны для вас.

Подробности об этом идут далее, но сначала несколько слов о модулях Golang.

Модули Golang

Моя любимая парадигма программирования – делать правильно. Я рассматриваю модульную систему как своего рода альтернативу объектно-ориентированной системе классов.

Module == Package == Module

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

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

В моем текущем приложении мне нужно манипулировать некоторыми строками в некоторых файлах и загружать их в AWS S3 как только я закончу.

Структура моего приложения выглядит так:

src
- my_app
- - main.go
- - main_test.go
- - uploader
- - - uploader.go
- - - uploader_test.go
- - replace_file_lines
- - - replace.go
- - - replace_test.go
- - - strings_util.go
- - - strings_util_test.go

Файлы с окончанием _test.go – это способ делать файлы модульного тестирования для Golang. Go имеет платформу тестирования, встроенную в ядро.

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

Вот пример того, как replace.go может выглядеть:


package replace_file_lines

import (
  // ...
)

// Variables that begin with an uppercase is exposed
var PublicVariable int = 42
// While those that begin with loweracse are private to the module
var privateVariable int = 0

// Function that begins with an uppercase is exposed
func Replace(oldFilePath, outputFilePath, with, what string) {
 // ... 
}

// Function that begins with an uppercase is exposed
func PublicFunction(/* .. */) {
  // ...
)

// While lowercase names makes functions private to the module
func privateFunction(/* .. */) {
  // ...
)

Если каталог имеет несколько файлов .go, то все методы и переменные относятся к пакету, даже закрытые (private). Это помогает разделить пакет на еще меньшие части и избежать больших одиночных файлов.

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

Golang gofmt

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

Or perhaps I am only happy because my side won in Go?

Читайте больше здесь: https://golang.org/cmd/gofmt/

Импорт Golang

Импорт всегда соотносится с GOPATH/src . Всегда. Я не преувеличиваю то, насколько это решение спасает меня от разочарований.

Предупреждение: следующее предложение сбивает с толку намерено.

При работе с другими языками вы можете использовать относительный или абсолютный импорт, или каким-то образом установить странный импорт, который позволит вам импортировать файл из непонятно-какого-расположения (я смотрю на тебя, Python).

Go решает эту проблему уникальным способом. Весь импорт, независимо от того, в каком файле он находится, всегда будет относителен GOPATH/src.

Поэтому в случае моего приложения импорт main будет выглядеть так:


package main

import (
 "my_app/replace_file_lines"
 "my_app/uploader"
 // ...
)

my_app находится в каталоге src, поэтому нам нужно сначала упомянуть его, затем мы импортируем пакеты, которые существуют под my_app, такие как uploader и replace_file_lines. Обратите внимание, что мы импортируем не отдельные файлы, а целые пакеты. Работает очаровательно и не вызывает никакой путаницы.

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

Ожидаете, что ваши программисты напишут чистый код без неиспользуемого импорта? Почему бы вам не позволить Суслику позаботиться об этом (прим. Суслик – маскот Golang)?


The Golang Get System

Импорт приводит нас к следующей замечательной функции Golang – go get. В то время как другие впечатлены менеджером пакетов JavaScripts NPM, Go просто использует любой репозиторий Git в качестве менеджера пакетов.

Как это работает?

Я писал раньше, что мне нужно было загрузить в S3, правильно? Ну, тогда это значит, что мне нужен пакет AWS SDK для этого. Чтобы сделать это, я просто открываю свой терминал и пишу:

go get github.com/aws/aws-sdk-go

Что здесь происходит? Ничего особенного, просто Golang загружает репозиторий из https://github.com/aws/aws-sdk-go в ваш каталог GOPATH/src.

Затем все, что вам нужно сделать, чтобы использовать aws-sdk, это просто импортировать его:


package uploader

import (
 "github.com/aws/aws-sdk-go/service/s3"
 "github.com/aws/aws-sdk-go/aws/session"
 "github.com/aws/aws-sdk-go/aws"
 // ...
)

Помните, что весь импорт соотносится с GOPATH/src? Из этого следует, что пакет s3, например, находится сейчас в GOPATH/src/github.com/aws/aws-sdk-go/services/s3.

Просто. Элегантно. Еще одно преимущество в копилку Суслика.

Системы пакетов и построения Golang

До сих пор мы фокусировались на GOPATH/src, но есть еще другие каталоги, на которые нужно обратить внимание: GOPATH/pkg и GOPATH/bin.

Golang является компилируемым языком, а значит для запуска код должен быть скомпилирован. Go компилируется быстро. Как это работает?

Каждый раз, когда вы компилируете свой код для запуска, Golang создает файл .a по тому же пути, что и ваш пакет, только в каталоге GOPATH/pkg. Если вы решили скомпилировать, например, aws-sdk, то он будет скомпилирован один раз. При этом он будет общим для всего остального вашего кода.

Конечно, это не единственная причина, по которой Golang компилируется быстро, но это просто вступление, которое поможет вам понять роль GOPATH/pkg.

Итак, что насчет GOPATH/bin? Когда вы запускаете команду go install, создается бинарный файл и помещается в GOPATH/bin. Файл получает имя каталога вашего основного пакета, в нашем случае это my_app.

Почему это так здорово? Ну, вы можете добавить GOPATH/bin в свою глобальную переменную PATH и все бинарные файлы вашей сборки доступны в командной строке без дополнительной работы! (Разве это не здорово? :D)

Кроссплатформенное построение Golang

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

Просто запустите:

GOOS=windows GOARCH=amd64 go install

И наш код выведет бинарный файл, готовый к развертыванию на машине с Windows. Этот .exe файл появится в GOPATH/bin/windows_amd64/my_app.exe. Проще простого.

Язык Golang

Golang стремится быть простым языком.

Мне нравится следующий пост с вопросом, почему Go не разрабатывался как функциональный язык: https://www.quora.com/Why-wasnt-Go-written-as-a-functional-language

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

И это просто. Вот список некоторых функций, которые Golang не поддерживает:

1. классы;

2. перегрузка операторов;

3. перегрузка функций

4. необязательные параметры;

5. исключения.

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

Иногда меня поражает, как быстро я могу достичь цели, когда пишу на Go, не имея многолетнего опыта, просто потому, что язык настолько приспособлен и ясен.

Параллелизм Golang

Я намерено оставил разговор о параллелизме напоследок. Почему? Потому что я не думаю, что это так важно.

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

Да, Golang имеет великолепную реализацию параллелизма. Вы не работаете с потоками, а скорее создаете дешевые goroutines, которые просты в создании и управлении. Goroutines позволяют распределять нагрузку по всем процессорам, не беспокоясь о том, как управлять всем этим.

Все еще заинтересованы в понимании goroutines? Читайте о них здесь: https://tour.golang.org/concurrency/1

Если вы хотите узнать больше о Go, я рекомендую книгу «The Go Programming Language» Алана А. А. Донована (Alan A. A. Donovan), который является частью команды Google Go, и Брайана У. Кернигана (Brian W. Kernighan), который является ветераном в области программной инженерии. Хотя этой книге два года (прим. – на момент выхода статьи), она всеобъемлюща и хорошо читается.


Оригинал - medium

Report Page