Урок 1: Установка Go, инструменты и первая программа

Урок 1. Установка Go, инструменты и первая программа

🔄 Node.js → Go (ключевые аналоги):

📋 Что изучаем

📦 Инициализация проекта

mkdir hello-go && cd hello-go
go mod init hello-go

После выполнения в директории появится файл go.mod — аналог package.json, но проще:

module hello-go

go 1.22

💻 Код программы

// main.go
// package main — обязателен для исполняемых программ.
// В Go программа начинается с пакета main, а не с произвольного файла.
package main

import (
    // Импортируем ТОЛЬКО используемые пакеты.
    // Неиспользуемый импорт = ошибка компиляции (goimports чистит автоматически).
    "flag"      // Аналог yargs/commander: парсинг аргументов командной строки
    "fmt"       // Форматированный ввод/вывод (как console.log + sprintf)
    "os"        // Взаимодействие с ОС: переменные окружения, stdin/stdout/stderr
    "strings"   // Манипуляции со строками
    "runtime"   // Информация о среде выполнения Go
)

// main() — точка входа. Без аргументов командной строки (для этого flag).
// В Go main() всегда синхронная. Для асинхронности — горутины (позже).
func main() {
    // flag.String() возвращает *string — УКАЗАТЕЛЬ на строку.
    // В Node.js: const name = yargs.argv.name || "World"
    // Здесь указатель нужен, чтобы flag.Parse() мог ИЗМЕНИТЬ значение.
    name := flag.String("name", "World", "имя для приветствия")
    
    // flag.Int() → *int
    repeat := flag.Int("repeat", 1, "количество повторений приветствия")
    
    // flag.Bool() → *bool
    loud := flag.Bool("loud", false, "вывести приветствие ЗАГЛАВНЫМИ буквами")
    
    // flag.Parse() парсит os.Args и заполняет значения флагов.
    // До вызова Parse() все флаги содержат значения по умолчанию.
    flag.Parse()

    // os.Getenv() — аналог process.env.KEY в Node.js
    // Возвращает пустую строку, если переменная не установлена.
    lang := os.Getenv("GREET_LANG")
    if lang == "" {
        lang = "en" // значение по умолчанию
    }

    // В Go НЕТ тернарного оператора (?:).
    // Это осознанное решение: код должен быть читаемым.
    // Используем switch — идиоматичный способ выбора.
    var greeting string
    switch lang {
    case "ru":
        greeting = "Привет"
    case "es":
        greeting = "¡Hola"
    case "de":
        greeting = "Hallo"
    case "fr":
        greeting = "Bonjour"
    case "it":
        greeting = "Ciao"
    default:
        greeting = "Hello"
    }

    // fmt.Sprintf — форматирование строки (аналог template literals)
    // *name — РАЗЫМЕНОВЫВАНИЕ указателя (получаем строку)
    message := fmt.Sprintf("%s, %s!", greeting, *name)

    // Условный оператор: если loud=true, переводим в верхний регистр
    if *loud {
        message = strings.ToUpper(message)
    }

    // for — ЕДИНСТВЕННЫЙ цикл в Go.
    // Он заменяет и for, и while, и do-while.
    for i := 0; i < *repeat; i++ {
        fmt.Println(message)
    }

    // === Информация о среде выполнения ===
    fmt.Printf("\n--- System Info ---\n")
    fmt.Printf("Go version: %s\n", runtime.Version())
    fmt.Printf("OS: %s\n", runtime.GOOS)
    fmt.Printf("Architecture: %s\n", runtime.GOARCH)
    
    // os.Hostname() возвращает (string, error) — МНОЖЕСТВЕННЫЙ ВОЗВРАТ.
    // В Go ошибки возвращаются, а не выбрасываются (нет try/catch).
    hostname, err := os.Hostname()
    if err != nil {
        // fmt.Fprintf с os.Stderr — вывод в поток ошибок
        fmt.Fprintf(os.Stderr, "Ошибка получения hostname: %v\n", err)
    } else {
        fmt.Printf("Hostname: %s\n", hostname)
    }
    
    // Демонстрация указателей (для понимания)
    x := 42
    ptr := &x        // & — оператор взятия адреса
    fmt.Printf("\n--- Демонстрация указателей ---\n")
    fmt.Printf("x = %d\n", x)
    fmt.Printf("&x = %p (адрес в памяти)\n", ptr)
    fmt.Printf("*ptr = %d (значение по адресу)\n", *ptr)
}

🚀 Запуск программы

# Базовый запуск (интерпретация + компиляция в кэш)
go run main.go

# С флагами командной строки
go run main.go -name "Gopher" -repeat 3 -loud

# С переменной окружения
GREET_LANG=ru go run main.go -name "Мир" -repeat 2

# Компиляция в нативный бинарный файл
go build -o greet main.go
./greet -name "Binary" -loud

# Кросс-компиляция для Linux
GOOS=linux GOARCH=amd64 go build -o greet-linux main.go

# Кросс-компиляция для Windows
GOOS=windows GOARCH=amd64 go build -o greet.exe main.go

# Кросс-компиляция для macOS (ARM — M1/M2)
GOOS=darwin GOARCH=arm64 go build -o greet-darwin main.go

# Просмотр всех supported OS/ARCH
go tool dist list

🔑 Ключевые концепции

Что нужно запомнить из этого урока:

💡 Для Node.js разработчика:

Следующий урок →