Почему Go — идеальный язык для автоматизации?
Вы когда-нибудь писали скрипт на Python, который отлично работал на вашем ноутбуке, но «падал» на сервере из-за отсутствия нужной версии интерпретатора? Или, может быть, ваш Bash-скрипт превращался в неподдерживаемого монстра, когда логика становилась чуть сложнее, чем «скопировать файл»?
Если да, то вам стоит присмотреться к Go. Этот язык был создан в недрах Google именно для решения проблем, с которыми сталкиваются инженеры при написании утилит и сервисов. Он компилируется в один бинарник (никаких зависимостей!), работает с космической скоростью и имеет простой, но мощный синтаксис.
В этой статье мы не будем учить вас основам синтаксиса. Мы сразу перейдем к делу: автоматизация задач на Go с реальными примерами кода. Вы узнаете, как написать свои первые «Go-скрипты», которые будут работать надежнее и быстрее их Python-аналогов. Поехали!
1. Работа с файловой системой: чистим логи как профи
Одна из самых частых задач админа или разработчика — чистка старых логов. Напишем утилиту, которая удаляет файлы старше N дней в заданной директории. Это классический пример автоматизации на Go.
package main
import (
"fmt"
"os"
"path/filepath"
"time"
)
func main() {
// Путь к директории с логами
logDir := "/var/log/myapp"
// Удаляем файлы старше 7 дней
maxAge := 7 * 24 * time.Hour
err := filepath.Walk(logDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// Пропускаем директории
if info.IsDir() {
return nil
}
// Проверяем возраст файла
if time.Since(info.ModTime()) > maxAge {
fmt.Printf("Удаляем старый файл: %s (возраст: %v)\n", path, time.Since(info.ModTime()))
err := os.Remove(path)
if err != nil {
fmt.Printf("Ошибка удаления %s: %v\n", path, err)
}
}
return nil
})
if err != nil {
fmt.Printf("Ошибка обхода директории: %v\n", err)
}
}
Этот код — отличный пример того, как автоматизировать задачи на Go без лишних библиотек. Встроенный пакет filepath рекурсивно обходит папки, а os.Remove очищает пространство. Скомпилировав его один раз, вы получаете бинарник, который можно запускать по cron на любом сервере.
2. HTTP-запросы и парсинг API
Допустим, вам нужно мониторить статус нескольких микросервисов или парсить данные с внешнего API. Go с его горутинами справляется с этим блестяще. Напишем скрипт, который проверяет доступность сайтов и отправляет уведомление, если что-то упало. Это еще один мощный пример автоматизации на Golang.
package main
import (
"fmt"
"net/http"
"sync"
"time"
)
func checkURL(url string, wg *sync.WaitGroup) {
defer wg.Done()
client := http.Client{
Timeout: 5 * time.Second,
}
resp, err := client.Get(url)
if err != nil {
fmt.Printf("[FAIL] %s - %v\n", url, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Printf("[WARN] %s - статус: %d\n", url, resp.StatusCode)
} else {
fmt.Printf("[OK] %s - работает\n", url)
}
}
func main() {
urls := []string{
"https://google.com",
"https://github.com",
"https://pythonlib.ru",
"https://non-existent-site.xyz",
}
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go checkURL(url, &wg) // Запускаем в горутине
}
wg.Wait() // Ждем завершения всех горутин
fmt.Println("Проверка завершена.")
}
Обратите внимание на sync.WaitGroup. Это ключевой паттерн в Go для ожидания завершения параллельных задач. Благодаря горутинам, ваш скрипт мониторинга проверит 100 сайтов быстрее, чем Python-скрипт проверит 10.
3. Парсинг логов в реальном времени
Иногда нужно не просто чистить логи, а анализировать их. Например, найти все IP-адреса из определенной подсети или подсчитать количество ошибок. Go идеален для парсинга логов благодаря своей производительности.
Предположим, у нас есть файл access.log стандартного формата Nginx. Мы хотим вывести все уникальные IP-адреса, с которых было больше 10 запросов.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
file, err := os.Open("access.log")
if err != nil {
fmt.Println("Ошибка открытия файла:", err)
return
}
defer file.Close()
ipCount := make(map[string]int)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// Первое поле в логе — это IP
parts := strings.Fields(line)
if len(parts) > 0 {
ip := parts[0]
ipCount[ip]++
}
}
if err := scanner.Err(); err != nil {
fmt.Println("Ошибка чтения:", err)
return
}
fmt.Println("IP-адреса с запросами > 10:")
for ip, count := range ipCount {
if count > 10 {
fmt.Printf("%s - %d запросов\n", ip, count)
}
}
}
Этот скрипт обрабатывает гигабайтные логи за секунды. Автоматизация задач на Go в данном случае позволяет вам не писать сложные однострочники на awk, а иметь читаемый и поддерживаемый код.
4. Отправка email-уведомлений
Крайне полезная задача — отправка писем. Допустим, вы написали скрипт бэкапа (на Go, конечно) и хотите получать отчет о его выполнении. В Go есть встроенная поддержка SMTP.
package main
import (
"fmt"
"net/smtp"
"os"
)
func sendEmail(to, subject, body string) error {
from := "your-email@gmail.com"
password := "your-app-password" // Используйте пароль приложения!
smtpHost := "smtp.gmail.com"
smtpPort := "587"
msg := []byte("To: " + to + "\r\n" +
"Subject: " + subject + "\r\n" +
"MIME-version: 1.0;\r\n" +
"Content-Type: text/plain; charset=\"UTF-8\";\r\n" +
"\r\n" +
body)
auth := smtp.PlainAuth("", from, password, smtpHost)
err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, []string{to}, msg)
if err != nil