Go: Как забыть про "У меня работает" и начать покорять миры
Вы когда-нибудь писали крутой скрипт на Python, отправляли его другу на Windows, а он отвечает: "Он у меня не запускается, какой-то питон не установлен"? Знакомо? Добро пожаловать в ад зависимостей, виртуальных окружений и версий интерпретаторов. А теперь представьте: вы написали код один раз, нажали одну кнопку — и получили бинарник, который работает на Windows, Linux и macOS без единой установки чего-либо. Без Python, без Node, без JVM.
Это не фантастика. Это кроссплатформенная разработка на Go — языке, который создавался для того, чтобы решать именно эти проблемы. Если вы пишете на Python и устали от танцев с бубном вокруг зависимостей, или если вы просто ищете инструмент для создания быстрых и переносимых утилит — Go станет вашим новым лучшим другом. В этой статье мы не будем лить воду. Мы разберем реальные примеры, покажем код и расскажем, как заставить вашу программу работать везде, где есть процессор.
Почему Go — это идеальный выбор для кроссплатформенности?
В мире Golang кроссплатформенность — это не фича, а фундамент. В отличие от Python, который требует интерпретатора, или Java, которой нужна виртуальная машина, Go компилируется в нативный машинный код. Это означает, что ваш бинарник содержит всё необходимое для работы: рантайм, сборщик мусора и ваш код. Никаких внешних библиотек, никаких "pip install". Скачал и запустил.
Но главное — это кросс-компиляция Go. Вы сидите на MacBook, пишете код, а затем одной командой собираете исполняемый файл для Windows, Linux, Raspberry Pi (ARM) или даже для древнего FreeBSD. Вам не нужна виртуалка или Docker для сборки. Одна переменная окружения — и готово.
Для разработчика на Python это звучит как магия, но это просто Go. Давайте перейдем к практике.
Пишем кроссплатформенную утилиту на Go
Представим, что нам нужно написать простую, но полезную программу: она будет собирать информацию о системе (ОС, архитектура, имя хоста) и сохранять её в JSON-файл. Это классическая задача для DevOps или системного администратора. На Python вы бы тащили platform и json, но на Go это выглядит еще элегантнее.
Шаг 1: Структура и импорт
Создайте файл main.go. Первое, что мы сделаем — это определим структуру данных и используем пакеты runtime и os для получения информации о системе. Обратите внимание: runtime.GOOS и runtime.GOARCH — это встроенные константы, которые Go знает еще на этапе компиляции.
package main
import (
"encoding/json"
"fmt"
"os"
"runtime"
)
type SystemInfo struct {
OS string `json:"os"`
Arch string `json:"arch"`
Hostname string `json:"hostname"`
GoVersion string `json:"go_version"`
}
Шаг 2: Сбор информации
Теперь напишем функцию, которая собирает данные. Мы используем os.Hostname() — она кроссплатформенная и работает на всех системах.
func getSystemInfo() (SystemInfo, error) {
hostname, err := os.Hostname()
if err != nil {
return SystemInfo{}, fmt.Errorf("ошибка получения hostname: %w", err)
}
return SystemInfo{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
Hostname: hostname,
GoVersion: runtime.Version(),
}, nil
}
Шаг 3: Запись в JSON
Завершим нашу программу: получим информацию, закодируем в JSON и запишем в файл. Мы также добавим обработку ошибок — это хороший тон в кроссплатформенной разработке на Go, так как пути к файлам различаются в разных ОС.
func main() {
info, err := getSystemInfo()
if err != nil {
fmt.Printf("Ошибка: %v\n", err)
os.Exit(1)
}
// Создаем или перезаписываем файл
file, err := os.Create("system_info.json")
if err != nil {
fmt.Printf("Ошибка создания файла: %v\n", err)
os.Exit(1)
}
defer file.Close()
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ")
if err := encoder.Encode(info); err != nil {
fmt.Printf("Ошибка записи JSON: %v\n", err)
os.Exit(1)
}
fmt.Println("Информация о системе сохранена в system_info.json")
}
Вот и всё. Это работает на любой платформе, где есть Go. Но подождите, мы же хотим, чтобы это работало там, где Go нет. Переходим к главному.
Магия кросс-компиляции: одна команда — три бинарника
Теперь самое интересное. Вы сидите на Linux, но хотите дать другу готовую программу под Windows. В Go это делается установкой двух переменных окружения: GOOS (целевая операционная система) и GOARCH (целевая архитектура).
Откройте терминал в папке с вашим проектом и выполните:
# Сборка для Windows (64-bit)
GOOS=windows GOARCH=amd64 go build -o system_info.exe main.go
# Сборка для Linux (64-bit)
GOOS=linux GOARCH=amd64 go build -o system_info_linux main.go
# Сборка для macOS (Intel)
GOOS=darwin GOARCH=amd64 go build -o system_info_mac main.go
# Сборка для macOS (Apple Silicon M1/M2)
GOOS=darwin GOARCH=arm64 go build -o system_info_mac_arm main.go
# Сборка для Raspberry Pi (ARM 32-bit)
GOOS=linux GOARCH=arm GOARM=6 go build -o system_info_arm main.go
Готово! У вас в папке лежат 5 бинарников. Никаких виртуальных машин, никаких Docker-образов. Просто сборка Go под разные ОС.
Важно: Если ваш код использует C-библиотеки (cgo), кросс-компиляция усложнится. Но в 99% случаев, особенно для утилит и микросервисов, cgo не нужен. Go стандартная библиотека — это всё, что вам нужно.
Продвинутые техники: условная компиляция
Иногда код должен вести себя по-разному на Windows и Linux. Например, пути к файлам: на Windows используется обратный слеш, на Linux — прямой. Go поддерживает условную компиляцию с помощью тегов сборки (build tags) и специальных имен файлов.
Создайте два файла:
config_unix.go (будет компилироваться только на Linux/macOS):
//go