Паттерны Go-кода на все случаи жизни

Паттерны Go-кода на все случаи жизни

Для временной очереди и спользуйте слайс. Для long-living очередей удобнее использовать динамическую структуру данных, такую как связанный список.

Паттерны Go-кода на все случаи жизни

Используем слайс

Простой способ реализовать временную структуру данных очереди в Go – использовать слайс:

  • для enqueue-запроса используйте встроенную функцию append ;
  • для dequeue-запроса – применяйте слайс к первому элементу.

Следим за утечками памяти Go

Возможно, вы захотите удалить первый элемент перед dequeue-запросом.

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

Связанный список

Пакет container/list реализует двусвязный список, который можно использовать в качестве очереди.

Паттерны Go-кода на все случаи жизни

Реализация множества через map

Распространенный способ реализации множества в Go – использование map .

Альтернативный подход

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

Паттерны Go-кода на все случаи жизни

В Go реализовать структуру данных стека (очередь LIFO) можно с помощью слайса и функции append :

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

Паттерны Go-кода на все случаи жизни

Для чтения и записи переменных окружения и спользуйте функции Setenv , Getenv , Unsetenv и Environ :

Паттерны Go-кода на все случаи жизни

В этом примере мы получаем доступ к несообщаемому полю len в структуре List пакета container/list :

Этот код считывает значение len с помощью рефлексии.

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

Паттерны Go-кода на все случаи жизни

Пример использования простой битовой маски в Go

Большие битсеты

Для представления больших битсетов может понадобиться кастомная структура данных. Есть удобный сторонний пакет bit, предоставляющий реализацию битового массива.

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

Паттерны Go-кода на все случаи жизни

Целочисленные типы

Для целочисленных типов используйте функцию ProbablyPrime(0) из пакета math/big . Этот тест на простые числа является 100% точным примерно для 2 64 вхождений.

Большие числа

Для больших чисел, необходимо обеспечить требуемое количество тестов из ProbablyPrime( n ) . Для n тестов вероятность возврата true для случайно выбранного непростого числа составляет не более (1/4) n . Для примера: при n = 20 на выходе получится 0,000,000,000,001.

Как написать базовое CLI-приложение.

Паттерны Go-кода на все случаи жизни

Этот пример является упрощенной версией команды grep из *nix. Код ищет в файле строки, содержащие заданный шаблон, и выводит их на экран.

Паттерны Go-кода на все случаи жизни

Вы можете получить доступ к аргументам командной строки, включая имя программы и флаги, через os.Args variable :

Кстати, пакет flag реализует базовый синтаксический анализ флагов командной строки.

Паттерны Go-кода на все случаи жизни

Целые числа

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

Памятка : наименьшее значение целого числа со знаком не имеет соответствующего положительного значения:

  • math.MinInt64 – это -9223372036854775808;
  • math.MaxInt64 – это 9223372036854775807.

К сожалению, в таких случаях функция Abs возвращает отрицательное значение:

Впрочем, подобным образом ведут себя б иблиотеки Java и C.

Float

Функция math.Abs может возвращать и абсолютные значения:

Паттерны Go-кода на все случаи жизни

Напишем код для вычисления минимума и максимума целых чисел. Используем math.Min и math.Max для чисел с плавающей точкой.

Float

Паттерны Go-кода на все случаи жизни

Функции для преобразования размера файла в байтах в удобочитаемый формат. Следующий код поддерживает и формат SI (десятичный), и IEC (двоичный).

Паттерны Go-кода на все случаи жизни

Строковая ошибка

Кастомные ошибки с данными

Для такого типа ошибок необходимо объявить error interface :

Если Foo – это функция, возвращающая SyntaxError или InternalError , их можно обработать следующим образом:

Для программного создания PNG-изображения обычно используются пакеты image , image/color и image/png .

Паттерны Go-кода на все случаи жизни

Верхний правый и нижний левый квадранты изображения прозрачны (значение <code равно 0) и будут иметь тот же цвет, что и фон.Верхний правый и нижний левый квадранты изображения прозрачны (значение alpha равно 0) и будут иметь тот же цвет, что и фон.

Паттерны Go-кода на все случаи жизни

Как сгенерировать все перестановки среза или строки в Go:

Паттерны Go-кода на все случаи жизни

Хэш строки

Чтобы вычислить хэш строки или байтового слайса, используйте функцию Sum пакетов crypto/md5 , crypto/sha1 или crypto/sha256 .

Хэш файла

Для вычисления хэша строки или потока:

  • создайте новый hash.Hash из пакета crypto/md5, crypto/sha1 или crypto/sha256;
  • добавьте данные, записав их в io.Writer ;
  • извлеките контрольную сумму функцией Sum .

Базовый веб-сервер

  • Вызов http.HandleFunc сообщает пакету net.http , что обработкой всех запросов к «корню» занимается HelloServer ;
  • http.ListenAndServe сообщает серверу, что он должен прослушивать адрес по порту 8080 . Эта функция блокируется, пока программа не завершится;
  • http.ResponseWriter отправляет данные HTTP-клиенту;
  • http.Request – структура данных клиентского HTTP-запроса;
  • r.URL.Path – компонент URL-адреса. В нашем случае “/world” является компонентом ссылки “http://localhost:8080/world” .

При обращении к http://localhost:8080/world , где работает приведенный код, вы увидите такую страницу:

Паттерны Go-кода на все случаи жизни

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

Базовый паттерн итератора

Итератор с break

Паттерны Go-кода на все случаи жизни

Йота: базовый пример

Ключевое слово iota позволяет создавать последовательные целочисленные константы: 0, 1, 2 и т. д. Значение iota сбрасывается к нулю, когда в исходном коде появляется слово const .

Можно уменьшить так:

Начало с единицы

Чтобы начать список констант с 1 вместо 0, можно использовать iota в арифметическом выражении:

Пропуск значения

Для пропуска значения в списке констант можно использовать п устой идентификатор:

Go имеет два целочисленных типа с реализацией конкретных размеров:

  • uint (беззнаковое целое), 32 или 64 бита;
  • int (целое) имеет такой же размер, как uint .

Код ниже вычисляет предельные значения нетипизированных констант:

Константа UintSize также доступна в пакете math/bits .

Float в string

Чтобы отобразить значение в виде строки, используйте метод fmt.Sprintf .

Float во Float

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

Пусть у нас есть код, который мы хотим протестить:

  • Поместим тестовый код в файл, имя которого заканчивается на _test.go ;
  • напишем функцию TestXXX с одним аргументом типа *testing.T;
  • для указания на неудачный тест, вызовем функцию t.Errorf .

Запустим тест с помощью go test :

Паттерны Go-кода на все случаи жизни

Сортировка слайса int, float64 или строк

Используем одну из функций:

Сортировка с помощью кастомного компаратора

Используйте функцию sort.Slice – о на сортирует слайс с помощью функции less(i, j int) . Чтобы отсортировать слайс, сохраняя исходный порядок элементов, используйте сортировку sort.SliceStable:

Сортировка пользовательских структур

Используйте универсальные функции sort.Sort и sort.Stable .

Сортировка map по ключу или значению

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

Если эти примеры были полезны, вы можете подписаться на наш телеграм-канал @goproglib – в нём мы публикуем последние статьи о языке Go и другие полезные материалы на русском и английском языках.