Go — удивительный язык с большим количеством импульсов, и он сосредоточен на простоте. Этот подход очевиден в его стандартной библиотеке, которая предоставляет все необходимое, но не намного.
К счастью, у Go есть активное сообщество, которое создает и разделяет множество сторонних библиотек. В этом уроке я познакомлю вас с 12 лучшими пакетами и библиотеками Go. Некоторые из них имеют относительно узкую область применения и могут быть добавлены в любые проекты, в то время как другие представляют собой огромные проекты, которые вы можете включить в массивные, масштабные распределенные системы.
Awesome Go
Прежде чем углубиться в сами библиотеки, позвольте мне познакомить вас с Awesome Go , очень активным и курируемым списком библиотек Go и другими ресурсами. Вы должны посещать время от времени и проверить, что нового.
1. Голанг-Сет
Go имеет массивы, фрагменты и карты, но не имеет заданной структуры данных. Вы можете имитировать набор с помощью карты bools, но хорошо иметь фактический тип данных с правильными операциями и семантикой. Вот где приходит golang-set . Вот базовый пример создания нового набора, добавления элементов и тестирования на членство:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package main
import (
«fmt»
«github.com/deckarep/golang-set»
)
func main() {
basicColors := mapset.NewSet()
basicColors.Add(«Red»)
basicColors.Add(«Blue»)
basicColors.Add(«Green»)
if basicColors.Contains(«Green») {
fmt.Println(«Yay! ‘Green’ is a basic color»)
} else {
fmt.Println(«What a disappointment! ‘Green’ is not a basic color»)
}
if basicColors.Contains(«Yellow») {
fmt.Println(«Yay! ‘Yellow’ is a basic color»)
} else {
fmt.Println(«What a disappointment! ‘Yellow’ is not a basic color»)
}
}
Output:
Yay!
What a disappointment!
|
Обратите внимание, что имя пакета «mapset». В дополнение к основам вы выполняете все операции над множествами, такие как объединение, пересечение и разность. Вы также можете перебирать установленные значения:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
package main
import (
«fmt»
«github.com/deckarep/golang-set»
)
func main() {
basicColors := mapset.NewSet()
basicColors.Add(«Red»)
basicColors.Add(«Blue»)
basicColors.Add(«Green»)
otherColors := mapset.NewSetFromSlice([]interface{}{«Orange», «Yellow», «Indigo», «Violet»})
rainbowColors := basicColors.Union(otherColors)
for color := range rainbowColors.Iterator().C {
fmt.Println(color)
}
}
|
2. Цвет
Давайте продолжим с цветовой темой. При написании программ командной строки полезно использовать цвета, чтобы выделить важные сообщения или отличить ошибки, успехи и предупреждения.
Пакет цветов дает простой способ добавить цвет в ваши программы (посмотрите, что я там делал?). Он использует управляющие коды ANSII и также поддерживает Windows! Вот быстрый пример:
01
02
03
04
05
06
07
08
09
10
|
package main
import (
«github.com/fatih/color»
)
func main() {
color.Red(«Roses are red»)
color.Blue(«Violets are blue»)
}
|
Пакет цветов поддерживает смешивание цветов с фоновыми цветами, стилями, такими как полужирный или курсив, и разбрызгивание цветов с выводом нецветных цветов.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
package main
import (
«github.com/fatih/color»
«fmt»
)
func main() {
minion := color.New(color.FgBlack).Add(color.BgYellow).Add(color.Bold)
minion.Println(«Minion says: banana!!!!!!»)
m := minion.PrintlnFunc()
m(«I want another banana!!!!!»)
slantedRed := color.New(color.FgRed, color.BgWhite, color.Italic).SprintFunc()
fmt.Println(«I’ve made a huge», slantedRed(«mistake»))
}
|
Пакет цветов имеет и другие полезные функции. Идите и исследуйте больше.
3. Сейчас
Теперь это очень простой пакет, который предоставляет удобную обертку для стандартного временного пакета и позволяет легко работать с различными конструкциями даты и времени вокруг текущего времени.
Например, вы можете получить начало текущей минуты или конец воскресенья, ближайший к текущему времени. Вот как использовать «сейчас»:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package main
import (
«github.com/jinzhu/now»
«fmt»
)
func main() {
fmt.Println(«All the beginnings…»)
fmt.Println(now.BeginningOfMinute())
fmt.Println(now.BeginningOfHour())
fmt.Println(now.BeginningOfDay())
fmt.Println(now.BeginningOfWeek())
fmt.Println(now.BeginningOfMonth())
fmt.Println(now.BeginningOfQuarter())
fmt.Println(now.BeginningOfYear())
}
Output:
All the beginnings…
2017-06-04 16:59:00 -0700 PDT
2017-06-04 16:00:00 -0700 PDT
2017-06-04 00:00:00 -0700 PDT
2017-06-04 00:00:00 -0700 PDT
2017-06-01 00:00:00 -0700 PDT
2017-04-01 00:00:00 -0700 PDT
2016-12-31 23:00:00 -0800 PST
|
Вы также можете анализировать время и даже добавлять свои собственные форматы (что потребует обновления известных форматов). Тип Now
встраивает time.Time
, поэтому вы можете использовать все методы time.Time
непосредственно для объектов Now
.
4. Генерал
Инструмент gen генерирует для вас код, в частности код с учетом типов, который пытается устранить пробел в отсутствии шаблонов или обобщений в Go.
Вы аннотируете свои типы специальным комментарием, и gen генерирует исходные файлы, которые вы включаете в свой проект. Никакой магии во время выполнения. Давайте посмотрим на пример. Вот аннотированный тип.
1
2
3
4
5
|
// +gen slice:»Where,Count,GroupBy[int]»
type Person struct {
Name string
Age int
}
|
Запуск gen
(убедитесь, что он на вашем пути) генерирует person_slice.go
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
// Generated by: gen
// TypeWriter: slice
// Directive: +gen on Person
package main
// PersonSlice is a slice of type Person.
type PersonSlice []Person
// Where returns a new PersonSlice whose elements return true for func.
func (rcv PersonSlice) Where(fn func(Person) bool) (result PersonSlice) {
for _, v := range rcv {
if fn(v) {
result = append(result, v)
}
}
return result
}
// Count gives the number elements of PersonSlice that return true for the passed func.
func (rcv PersonSlice) Count(fn func(Person) bool) (result int) {
for _, v := range rcv {
if fn(v) {
result++
}
}
return
}
// GroupByInt groups elements into a map keyed by int.
func (rcv PersonSlice) GroupByInt(fn func(Person) int) map[int]PersonSlice {
result := make(map[int]PersonSlice)
for _, v := range rcv {
key := fn(v)
result[key] = append(result[key], v)
}
return result
}
|
Код предоставляет LINQ-подобные методы для работы с типом PersonSlice
. Это легко понять и хорошо задокументировано.
Вот как вы это используете. В основной функции определена PersonSlice
. Функция age()
выбирает поле age из аргумента Person
. Сгенерированная GroupByInt()
берет функцию age()
и возвращает людей из среза, сгруппированного по возрасту (34 — это просто Джим, но 23 имеет и Джейн, и Кайла).
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package main
import (
«fmt»
)
// +gen slice:»Where,Count,GroupBy[int]»
type Person struct {
Name string
Age int
}
func age(p Person) int {
return p.Age
}
func main() {
people := PersonSlice {
{«Jim», 34},
{«Jane», 23},
{«Kyle», 23},
}
groupedByAge := people.GroupByInt(age)
fmt.Println(groupedByAge)
}
Output:
map[34:[{Jim 34}] 23:[{Jane 23} {Kyle 23}]]
|
5. Горм
Го известен своей спартанской природой. Программирование баз данных не отличается. Самые популярные библиотеки БД для Go довольно низкоуровневые. Gorm привносит в Go мир объектно-реляционного отображения со следующими функциями:
- Ассоциации (имеет один, имеет много, принадлежит, много ко многим, полиморфизм)
- Обратные вызовы (до / после создания / сохранения / обновления / удаления / поиска)
- Предварительная загрузка (готовая загрузка)
- операции
- Составной первичный ключ
- SQL Builder
- Авто Миграции
- лесоруб
- Расширяемый, писать плагины на основе обратных вызовов GORM
Но это не охватывает все. Если вы пришли из Python, не ожидайте магии SQLAlchemy. Для более причудливых вещей, вам придется перейти на более низкий уровень. Вот пример того, как использовать Gorm с sqlite. Обратите внимание на встроенный gorm.Model
в структуре Product.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package main
import (
«github.com/jinzhu/gorm»
_ «github.com/jinzhu/gorm/dialects/sqlite»
)
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
db, err := gorm.Open(«sqlite3», «test.db»)
if err != nil {
panic(«failed to connect database»)
}
defer db.Close()
// Migrate the schema
db.AutoMigrate(&Product{})
// Create
db.Create(&Product{Code: «L1212», Price: 1000})
// Read
var product Product
db.First(&product, 1) // find product with id 1
db.First(&product, «code = ?», «L1212»)
// Update — update product’s price to 2000
db.Model(&product).Update(«Price», 2000)
// Delete — delete product
db.Delete(&product)
|
6. Гусь
Одной из наиболее важных задач при работе с реляционными базами данных является управление схемой. В некоторых организациях изменение схемы БД считается «страшным» изменением. Пакет Goose позволяет выполнять изменения схемы и даже миграцию данных при необходимости. Вы можете goose up
и goose down
чтобы идти вперед и назад. Следите за своими данными, хотя, и убедитесь, что они не будут потеряны или повреждены.
Goose работает путем создания версий вашей схемы и использования файлов миграции, соответствующих каждой схеме. Файлы миграции могут быть командами SQL или командами Go. Вот пример файла миграции SQL, который добавляет новую таблицу:
01
02
03
04
05
06
07
08
09
10
|
— +goose Up
CREATE TABLE person (
id int NOT NULL,
name text,
age int,
PRIMARY KEY(id)
);
— +goose Down
DROP TABLE person;
|
Комментарии -- +goose up
и -- +goose down
сообщают goose, что нужно сделать, чтобы улучшить или понизить схему.
7. скользить
Glide — менеджер пакетов для Go. Под одной GOPATH
вас может быть много программ, которые имеют конфликтующие зависимости. Решение состоит в том, чтобы каждая программа управляла своим собственным каталогом поставщиков зависимостей пакетов. Glide помогает с этой задачей.
Вот особенности скольжения:
- Пакеты поддержки версий, включая поддержку Semantic Versioning 2.0.0.
- Поддержка псевдонимов пакетов (например, для работы с вилками github).
- Устранить необходимость в импровизированных операторах импорта.
- Работайте со всеми инструментами go.
- Поддержите все инструменты VCS, которые поддерживает Go (git, bzr, hg, svn).
- Поддержка пользовательских локальных и глобальных плагинов.
- Кэширование репозитория и данных для повышения производительности.
- Сглаживание зависимостей, устранение различий в версиях и избежание многократного включения пакета.
- Управляйте и устанавливайте зависимости по требованию или продавцу в вашей системе контроля версий.
Зависимости хранятся в glide.yaml , и glide предоставляет несколько команд для управления зависимостями:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
create, init Initialize a new project, creating a
glide.yaml file
config-wizard, cw Wizard that makes optional suggestions
to improve config in a glide.yaml file.
get Install one or more packages into
`vendor/` and add dependency to
glide.yaml.
remove, rm Remove a package from the glide.yaml
file, and regenerate the lock file.
import Import files from other dependency
management systems.
name Print the name of this project.
novendor, nv List all non-vendor paths in a
directory.
rebuild Rebuild (‘go build’) the dependencies
install, i Install a project’s dependencies
update, up Update a project’s dependencies
tree (Deprecated) Tree prints the
dependencies of this project as a tree.
list List prints all dependencies that the
present code references.
info Info prints information about this
project
cache-clear, cc Clears the Glide cache.
about Learn about Glide
mirror Manage mirrors
help, h Shows a list of commands or help for
one command
|
8. Гинкго
Ginkgo — это среда тестирования BDD (Behavior Driven Development). Это позволяет вам писать тесты в синтаксисе, напоминающем английский, и позволяет менее техническим специалистам просматривать тесты (и их результаты) и проверять, соответствуют ли они бизнес-требованиям.
Некоторым разработчикам нравится этот стиль спецификации теста. Он интегрируется со встроенным пакетом тестирования Go и часто сочетается с Gomega . Вот пример теста Гинкго + Гомега:
1
2
3
4
|
actual, err := foo()
Ω(err).Should(BeNil())
Ω(actual).ShouldNot(BeNil())
Ω(actual.result).Should(Equal(100))
|
9. и т. Д.
Etcd — надежный распределенный магазин Key-Value. Сервер реализован на Go, и клиент Go взаимодействует с ним через gRPC .
Основное внимание уделяется следующему:
- Просто: четко определенный пользовательский API (gRPC).
- Безопасный: автоматический TLS с опциональной аутентификацией сертификата клиента.
- Быстро: 10 000 записей в секунду.
- Надежно: правильно распространяется с помощью Raft.
Вот пример подключения к серверу, установки значения и его получения, включая таймауты и очистку.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
func test_get() {
cli, err := clientv3.New(clientv3.Config{
Endpoints: endpoints,
DialTimeout: dialTimeout,
})
if err != nil {
log.Fatal(err)
}
defer cli.Close()
_, err = cli.Put(context.TODO(), «foo», «bar»)
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(),
requestTimeout)
resp, err := cli.Get(ctx, «foo»)
cancel()
if err != nil {
log.Fatal(err)
}
for _, ev := range resp.Kvs {
fmt.Printf(«%s : %s\n», ev.Key, ev.Value)
}
// Output: foo : bar
}
|
10. NSQ
NSQ — отличная распределенная очередь. Я успешно использовал его в качестве основного строительного блока для крупных распределенных систем. Вот некоторые из его особенностей:
- Поддержка распределенных топологий без SPOF.
- Горизонтально масштабируемый (без посредников, легко добавляйте больше узлов в кластер).
- Доставка сообщений с низкой задержкой (производительность).
- Комбинированная маршрутизация сообщений с балансировкой нагрузки и многоадресным стилем.
- Excel как для потоковых (с высокой пропускной способностью), так и для ориентированных на работу (с низкой пропускной способностью) рабочих нагрузок.
- В основном в памяти (за пределами отметки верхнего уровня сообщения прозрачно хранятся на диске).
- Служба обнаружения времени выполнения для потребителей, чтобы найти производителей (nsqlookupd).
- Безопасность транспортного уровня (TLS).
- Формат данных не зависит.
- Несколько зависимостей (простота развертывания) и разумная ограниченная конфигурация по умолчанию.
- Простой протокол TCP с поддержкой клиентских библиотек на любом языке.
- HTTP-интерфейс для статистики, действий администратора и производителей (для публикации не требуется клиентская библиотека).
- Интегрируется со statsd для инструментовки в реальном времени.
- Надежный интерфейс администрирования кластера (nsqadmin).
Вот как опубликовать сообщение в NSQ (обработка ошибок исключена):
01
02
03
04
05
06
07
08
09
10
11
12
13
|
package main
import (
«github.com/bitly/go-nsq»
)
func main() {
config := nsq.NewConfig()
p, _ := nsq.NewProducer(«127.0.0.1:4150», config)
p.Publish(«topic», []byte(«message»))
p.Stop()
}
|
А вот как потреблять:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package main
import (
«sync»
«fmt»
«github.com/bitly/go-nsq»
)
func main() {
wg := &sync.WaitGroup{}
wg.Add(1)
config := nsq.NewConfig()
q, _ := nsq.NewConsumer(«topic», «channel», config)
handler := nsq.HandlerFunc(func(message *nsq.Message) error {
fmt.Printf(«Got a message: %v», message)
wg.Done()
return nil
})
q.AddHandler(handler)
q.ConnectToNSQD(«127.0.0.1:4150»)
wg.Wait()
}
|
11. Докер
Docker теперь является домохозяйством (если члены вашей семьи в основном люди DevOps). Вы можете не знать, что Docker реализован на Go. Обычно вы не используете Docker в своем коде, но это значительный проект, заслуживающий признания в качестве чрезвычайно успешного и популярного проекта Go.
12. Кубернетес
Kubernetes — это платформа оркестрации контейнеров с открытым исходным кодом для облачных приложений. Это еще одна распределенная система монстров, реализованная в Go. Недавно я написал книгу « Освоение кубернетов», в которой подробно описываю самые продвинутые аспекты кубернетов. С точки зрения разработчика Go, Kubernetes очень гибок, и вы можете расширять и настраивать его с помощью плагинов.
Вывод
Go это отличный язык. Его философия дизайна — быть простым и доступным языком. Его стандартная библиотека не такая всеобъемлющая, как некоторые другие языки, такие как Python.
Сообщество Go активизировалось, и есть много высококачественных библиотек, которые вы можете использовать в своих программах. В этой статье я представил 12 библиотек. Я призываю вас искать другие библиотеки, прежде чем приступить к реализации и реализовать все с нуля.