Перейти к основному содержимому

Простые приложения на Go

Разработчику Архитектору

Простые приложения на Go

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


Как запускать примеры из главы

  1. Сохраните код в файл .go с package main (имя — в Как запустить).
  2. В каталоге с файлом: go run имя_файла.go
go run имя_файла.go

Разбор:

  • go run выполняет быструю проверку примера без отдельного шага сборки бинарника.
  • Команда компилирует код во временный артефакт и сразу запускает его.
  • Такой режим удобен для обучения, потому что сокращает цикл "изменил код -> увидел результат".
  1. Для нескольких файлов в модуле: go mod init example один раз, затем go run .
go mod init example

Разбор:

  • go mod init example создаёт файл go.mod и включает модульный режим.
  • После этого зависимости фиксируются версиями и проект собирается воспроизводимо.
  • Команду выполняют один раз в корне нового проекта.

Проверка: go version (Go 1.21+).


Генератор паролей

Генератор паролей демонстрирует работу со строками, массивами символов и генерацией случайных чисел. Стандартная библиотека math/rand позволяет создавать криптографически стойкие последовательности через пакет crypto/rand.


Как запустить

  • Файл: password.go
  • Команда: go run password.go
go run password.go
  • Нужно: только stdlib.
  • Результат: Сгенерированный пароль: ...

Код примера

Код ITЗагрузка примера кода…

Разбор:

  • generatePassword(length int) формирует пароль заданной длины и возвращает строку.
  • crypto/rand используется для криптографически стойкой генерации, что важно для паролей.
  • Буфер []byte заполняется случайными индексами символов из charset.
  • rand.Int(rand.Reader, big.NewInt(...)) ограничивает диапазон значений границами набора символов.
  • string(password) превращает байтовый срез в итоговый пароль для вывода.

Разбор кода

  • Пакет crypto/rand: Используется вместо math/rand для получения безопасных случайных чисел, что критично для генерации паролей.
  • Структура данных []byte: Слайс байтов используется как буфер для хранения символов будущего пароля. Это эффективно по памяти.
  • Цикл for range: Итерация по слайсу автоматически определяет индекс и значение элемента.
  • Преобразование типов: Функция num.Int64() преобразует большое целое число из big.Int в стандартный тип int64 для использования в качестве индекса строки.

Сортировщик текстового файла

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


Как запустить

  • Файл: sort_file.go
  • Подготовка: input.txt рядом с программой; укажите пути в main.
  • Команда: go run sort_file.go
go run sort_file.go
  • Результат: output.txt с отсортированными строками.

Код примера

Код ITЗагрузка примера кода…


Разбор кода

  • bufio.Scanner: Эффективный инструмент для посимвольного или построчного чтения больших файлов без загрузки всего содержимого в память.
  • strings.TrimSpace: Удаляет пробелы и символы перевода строки по краям каждой строки перед обработкой.
  • sort.Strings: Встроенная функция сортировки, которая использует алгоритм быстрой сортировки (quicksort) для упорядочивания слайса строк.
  • defer: Обеспечивает закрытие файловых дескрипторов при выходе из функции, предотвращая утечки ресурсов.
  • writer.Flush(): Явно сбрасывает буфер вывода на диск, гарантируя сохранение данных.

Консольный калькулятор

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


Как запустить

  • Файл: calculator.go
  • Команда: go run calculator.go
go run calculator.go
  • Нужно: интерактивный терминал.
  • Результат: цикл вычислений до выхода.

Код примера

Код ITЗагрузка примера кода…


Разбор кода

  • Тип float64: Используется для представления вещественных чисел с высокой точностью.
  • switch: Конструкция выбора действия, которая четко разделяет логику для каждого оператора.
  • Обработка ошибок: Возврат ошибки при попытке деления на ноль или вводе некорректной операции.
  • strconv.ParseFloat: Преобразование строкового ввода в числовой тип с проверкой на корректность формата.

Трекер задач в JSON

Как запустить

  • Файл: tasks.go (блок "Код реализации")
  • Команда: go run tasks.go
go run tasks.go
  • Результат: tasks.json, список задач в консоли.

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


Структура данных

type Task struct {
ID int `json:"id"`
Title string `json:"title"`
Done bool `json:"done"`
Priority int `json:"priority"` // 1-высокий, 5-низкий
}

type TaskList struct {
Tasks []Task `json:"tasks"`
}

Код реализации

Код ITЗагрузка примера кода…


Разбор кода

  • Теги json:"...": Позволяют управлять именами полей в JSON-структуре. Например, поле Done сохраняется как done.
  • encoding/json: Стандартный пакет для работы с форматом JSON.
  • json.MarshalIndent: Преобразует структуру в строку JSON с отступами для удобного чтения человеком.
  • os.WriteFile: Современный аналог создания и записи файла с указанием прав доступа (0644).
  • Логика ID: Простая эвристика для генерации уникального идентификатора на основе последнего элемента списка.

Простой HTTP-сервер и клиент

Как запустить

  • Файлы: server.go, client.go (блоки ниже).
  • Терминал 1: go run server.go
go run server.go
  • Терминал 2: go run client.go
go run client.go
  • Остановка: Ctrl+C на сервере.

Подробнее: Веб на стандартной библиотеке · TCP и UDP.

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


Серверная часть

Код ITЗагрузка примера кода…


Клиентская часть

Код ITЗагрузка примера кода…


Разбор кода

  • http.HandleFunc: Регистрирует функцию обработки запросов для конкретного URL-пути.
  • r.URL.Query().Get("name"): Извлекает параметры из строки запроса (например, ?name=Value).
  • http.Response: Объект ответа содержит статус код, заголовки и тело ответа.
  • io.ReadAll: Чтение всего тела ответа в байтовый срез.
  • defer resp.Body.Close(): Обязательная практика для освобождения сетевого ресурса после завершения работы.

Отправитель HTTP-запросов (с кастомными параметрами)

Этот пример расширяет функциональность клиента, позволяя отправлять POST-запросы с произвольными данными и заголовками.


Как запустить

  • Файл: http_post.go
  • Команда: go run http_post.go (сервер уже запущен).
go run http_post.go
  • Результат: статус и тело ответа.

Код примера

Код ITЗагрузка примера кода…


Разбор кода

  • http.NewRequest — Создает объект запроса с указанным методом (GET, POST, PUT и т.д.) и телом.
  • bytes.NewBuffer: Позволяет использовать байтовый срез как поток данных для тела запроса.
  • req.Header.Set: Установка пользовательских заголовков, важных для идентификации клиента или формата данных.
  • client.Do: Выполняет запрос и возвращает ответ, позволяя настроить таймауты и редиректы через структуру http.Client.

Утилита для сканирования директорий

Инструмент для обхода файловой системы и сбора информации о файлах и подпапках.


Как запустить

  • Файл: scan.go
  • Команда: go run scan.go
go run scan.go
  • Результат: список файлов и суммарный размер.

Код примера

Код ITЗагрузка примера кода…


Разбор кода

  • filepath.Walk: Рекурсивно проходит по всей структуре директории, вызывая функцию для каждого найденного пути.
  • os.FileInfo — Структура, содержащая метаданные файла (размер, права доступа, время изменения).
  • info.IsDir(): Метод для определения типа объекта (файл или каталог).
  • filepath.Rel: Вычисление относительного пути для красивого отображения структуры.

Скрипт для создания резервного копирования файлов

Автоматизация процесса дублирования файлов с добавлением временной метки к имени копии.


Как запустить

  • Файл: backup.go
  • Команда: go run backup.go
go run backup.go
  • Результат: копия в каталоге бэкапов с датой в имени.

Код примера

Код ITЗагрузка примера кода…


Разбор кода

  • time.Now().Format: Форматирование даты в строку, пригодную для имени файла (ISO 8601 стиль адаптирован под Windows/Linux).
  • io.Copy: Оптимизированная функция для побайтового копирования данных между потоками.
  • os.MkdirAll — Создание директории, если она не существует, включая все необходимые промежуточные уровни.
  • filepath.Join: Корректное объединение путей с учетом разделителей для разных операционных систем.

Мониторинг дискового пространства

Утилита проверяет свободное место на диске и выводит статистику в процентах и абсолютных значениях.


Как запустить

  • Файл: disk.go
  • Команда: go run disk.go
go run disk.go
  • Результат: свободно/занято на выбранном диске.

Код примера

Код ITЗагрузка примера кода…

Примечание: Стандартная библиотека Go не предоставляет прямой функции для получения общего объема диска и свободного места. Для этого обычно используют пакет syscall (Unix) или golang.org/x/sys/windows. Приведенный код демонстрирует структуру программы, готовую к интеграции системных вызовов.


Парсер URL и проверка доступности ресурса

Инструмент анализирует компоненты URL (хост, путь, порт) и проверяет, доступен ли сервер по этому адресу.


Как запустить

  • Файл: url_check.go
  • Команда: go run url_check.go
go run url_check.go
  • Нужно: сеть.
  • Результат: статус и доступность URL.

Код примера

Код ITЗагрузка примера кода…


Разбор кода

  • url.Parse — Разбивает строку URL на составные части (схема, хост, порт, путь).
  • parsedURL.Port(): Извлекает номер порта, если он явно указан.
  • client.Head — Отправка запроса метода HEAD, который получает только заголовки без тела ответа, что экономит трафик.
  • Timeout: Ограничение времени ожидания ответа для предотвращения зависания программы при недоступном сервере.

Конвертер форматов дат

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


Как запустить

  • Файл: dates.go
  • Команда: go run dates.go
go run dates.go
  • Результат: дата в новом формате в stdout.

Код примера

Код ITЗагрузка примера кода…


Разбор кода

  • time.ParseInLocation: Парсинг строки в объект time.Time с учетом временной зоны.
  • t.Format: Преобразование объекта времени в строку по заданному шаблону.
  • Шаблон 2006-01-02: В Go используется специальное эталонное время Mon Jan 2 15:04:05 MST 2006 для определения формата. Любая дата в коде должна соответствовать этому шаблону.

Утилита для просмотра запущенных процессов

Отображение списка активных процессов с их идентификаторами (PID) и командами запуска.


Как запустить

  • Файл: ps.go
  • Команда: go run ps.go
go run ps.go
  • Результат: таблица процессов ОС.

Код примера

Код ITЗагрузка примера кода…

Примечание: Для реальной работы с процессами в Go рекомендуется использовать пакеты вроде github.com/shirou/gopsutil, так как прямое выполнение команд (exec.Command) зависит от ОС и требует наличия специфических утилит. Данный пример демонстрирует принцип взаимодействия с оболочкой.


Дополнительные сниппеты с разбором

HTTP-клиент с таймаутом и проверкой статуса

client := &http.Client{Timeout: 3 * time.Second}
resp, err := client.Get("https://example.com")
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode >= 400 {
return fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

Разбор:

  • Timeout ограничивает ожидание и защищает CLI от зависания на сетевых вызовах.
  • defer resp.Body.Close() обязателен для освобождения соединения.
  • Проверка диапазона >= 400 позволяет единообразно обрабатывать ошибки HTTP.
  • Такой шаблон подходит для большинства утилит, работающих с внешними API.

Пайплайн обработки строк через канал

in := make(chan string)
out := make(chan string)

go func() {
defer close(out)
for s := range in {
out <- strings.ToUpper(strings.TrimSpace(s))
}
}()

Разбор:

  • Канал in принимает исходные данные, а out отдаёт нормализованный результат.
  • range in продолжает работу, пока входной канал не будет закрыт.
  • defer close(out) корректно завершает downstream-этапы пайплайна.
  • Сниппет показывает основу для многослойной потоковой обработки данных в Go.

Характерный пример именно для Go — Горизонтальная масштабируемость через Горутины

Главная особенность языка Go — это нативная поддержка параллелизма через горутины (goroutines) и каналы (channels). Ниже приведен пример, который обрабатывает список URL параллельно, используя ограниченное количество горуток.


Как запустить

  • Файл: goroutines.go
  • Команда: go run goroutines.go
go run goroutines.go
  • Нужно: сеть для URL из примера.
  • Результат: параллельные ответы или ошибки по каждому адресу.

Код ITЗагрузка примера кода…

Разбор:

  • sync.WaitGroup гарантирует, что итоговый вывод начнётся только после завершения всех goroutine.
  • Канал semaphore с буфером workers ограничивает параллелизм и предотвращает перегрузку сети.
  • Каждая goroutine выполняет HEAD-запрос и сохраняет статус или ошибку в структуру Result.
  • defer func() { <-semaphore }() освобождает слот даже при раннем выходе по ошибке.
  • time.Since(start) измеряет реальное время параллельной обработки списка URL.

Разбор кода

  • go func(...): Запуск функции в отдельной горуток. Горутина потребляет минимум памяти и переключается очень быстро.
go func(...)
  • sync.WaitGroup: Синхронизатор, позволяющий основной программе ждать завершения всех запущенных горуток.
  • chan struct{} (Семафор): Канал пустого типа, ограничивающий максимальное количество одновременно работающих горуток. Это защищает систему от перегрузки.
  • defer: Гарантирует освобождение ресурса канала даже при возникновении ошибки внутри горутины.
  • time.Since: Подсчет времени выполнения блока кода для оценки производительности.

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


Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.

Содержание