Команда Go for Devs подготовила перевод пошагового руководства: как написать собственное CLI-приложение прогноза погоды на Go. Проект охватывает всё — от HTTP-запросов и парсинга JSON до удобного интерфейса командной строки. Отличная практика для новичков и хороший повод освежить базовые навыки тем, кто уже работает с Go.
Сегодня мы займёмся увлекательным проектом — напишем CLI-приложение прогноза погоды на Go. В этой статье я проведу вас через все шаги создания собственного консольного приложения для получения погоды. Независимо от того, только ли вы начинаете изучать Go или ищете интересный проект для практики — этот туториал вам подойдёт.
Мы разберём всё: от настройки проекта и написания кода до тестирования приложения. И обещаю — каждую строчку кода я объясню так, чтобы вы точно понимали, что происходит «под капотом».
Так что берите любимый напиток, открывайте редактор — и поехали писать код!
Настройка проекта
Прежде чем приступить к написанию кода, давайте определимся с целью. Мы хотим создать CLI-приложение на Go, которое будет получать данные о погоде с онлайн-API и показывать их в терминале. В качестве источника данных используем OpenWeatherMap. Если у вас ещё нет API-ключа, обязательно зарегистрируйтесь и получите бесплатный ключ.
Наше приложение будет выполнять следующие шаги:
Принимать на вход название города.
Обращаться к API прогноза погоды.
Разбирать JSON-ответ.
Отображать текущую информацию о погоде.
Этот проект прост, но при этом полезен. Следуя инструкциям, вы получите практический опыт работы с HTTP-запросами, парсингом JSON и созданием консольных интерфейсов в Go.
Понимание работы CLI-приложения прогноза погоды
Прежде чем переходить к коду, разберёмся, что именно будет делать наше CLI-приложение на Go:
Ввод пользователя. Приложение будет запрашивать у пользователя название города или принимать его как аргумент командной строки.
HTTP-запрос. С помощью встроенного пакета Go
net/httpмы отправим HTTP GET-запрос к API OpenWeatherMap.Парсинг JSON. После получения ответа мы преобразуем JSON-данные в структуры Go.
Отображение данных. В конце красиво выведем детали прогноза погоды (температуру, влажность и описание) в терминал.
Шаг 1: Создание проекта и инициализация модулей
Для начала создадим папку проекта и инициализируем модуль Go.
Создайте новую директорию для проекта:
mkdir weather-cli-app cd weather-cli-app
Инициализируйте модуль Go:
go mod init weather-cli-app
Эта команда создаст файл go.mod, в котором будут отслеживаться зависимости проекта. Теперь у нас есть чистая основа для создания CLI-приложения прогноза погоды на Go.
Шаг 2: Настройка API-клиента
Теперь, когда проект готов, нужно создать API-клиент для получения данных о погоде. Мы напишем простую функцию, которая будет отправлять HTTP GET-запрос к OpenWeatherMap.
Создайте новый файл weather.go:
touch weather.go
Добавьте следующий код в weather.go:
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "os" ) // WeatherData — структура под JSON-ответ OpenWeatherMap. type WeatherData struct { Name string `json:"name"` Main struct { Temp float64 `json:"temp"` Humidity int `json:"humidity"` } `json:"main"` Weather []struct { Description string `json:"description"` } `json:"weather"` } // getWeatherData получает данные о погоде для указанного города. func getWeatherData(city string, apiKey string) (*WeatherData, error) { // Формируем URL API. Используем метрическую систему (градусы Цельсия). url := fmt.Sprintf("http://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric", city, apiKey) // Отправляем HTTP-запрос. resp, err := http.Get(url) if err != nil { return nil, fmt.Errorf("failed to make request: %v", err) } defer resp.Body.Close() // Проверяем, что запрос прошёл успешно. if resp.StatusCode != http.StatusOK { bodyBytes, _ := ioutil.ReadAll(resp.Body) return nil, fmt.Errorf("error: received status code %d: %s", resp.StatusCode, string(bodyBytes)) } // Читаем тело ответа. bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %v", err) } // Декодируем JSON в структуру WeatherData. var weather WeatherData err = json.Unmarshal(bodyBytes, &weather) if err != nil { return nil, fmt.Errorf("failed to decode JSON: %v", err) } return &weather, nil }
Пояснение к коду:
Мы объявляем структуру
WeatherData, которая соответствует JSON-ответу OpenWeatherMap. Это позволяет удобно декодировать данные из API.Функция принимает название города и API-ключ: она собирает URL запроса, отправляет HTTP GET и обрабатывает ответ. В случае успеха JSON разбирается в структуру
WeatherData.
Следуя этим шагам, вы получили рабочий компонент API-клиента для вашего CLI-приложения погоды на Go.
Шаг 3: Создаём интерфейс командной строки
Теперь настроим интерфейс командной строки. Пользователь сможет передать название города прямо при запуске приложения. Если этого не сделать, программа запросит ввод интерактивно.
Создайте файл main.go:
touch main.go
Добавьте следующий код в main.go:
package main import ( "bufio" "fmt" "os" "strings" ) func main() { // Читаем API-ключ из переменной окружения. apiKey := os.Getenv("OPENWEATHER_API_KEY") if apiKey == "" { fmt.Println("Error: Please set the OPENWEATHER_API_KEY environment variable.") os.Exit(1) } // Проверяем, передано ли название города в аргументах командной строки. var city string if len(os.Args) > 1 { city = strings.Join(os.Args[1:], " ") } else { // Запрашиваем у пользователя название города, если аргумент не указан. fmt.Print("Enter the city name: ") reader := bufio.NewReader(os.Stdin) input, err := reader.ReadString('\n') if err != nil { fmt.Println("Error reading input:", err) return } city = strings.TrimSpace(input) } // Получаем данные о погоде. weather, err := getWeatherData(city, apiKey) if err != nil { fmt.Println("Error fetching weather data:", err) return } // Отображаем данные о погоде. displayWeatherData(weather) }
Пояснение к коду:
API-ключ считывается из переменной окружения
OPENWEATHER_API_KEY. Такой способ позволяет безопасно хранить чувствительные данные.Программа проверяет, указал ли пользователь название города в аргументах командной строки. Если нет, она предложит ввести его вручную.
После получения названия города вызывается функция
getWeatherData, а затем данные передаются для отображения.
Этот фрагмент объединяет воедино интерфейс командной строки нашего CLI-приложения прогноза погоды на Go.
Шаг 4: Парсим и отображаем данные о погоде
Теперь нам нужна функция, которая красиво отформатирует и выведет данные о погоде. Она будет принимать данные, полученные от API, и печатать их в терминале.
В том же файле main.go добавьте следующую функцию:
// displayWeatherData выводит информацию о погоде в удобном для пользователя формате. func displayWeatherData(weather *WeatherData) { fmt.Printf("\nWeather for %s:\n", weather.Name) if len(weather.Weather) > 0 { fmt.Printf("Description: %s\n", strings.Title(weather.Weather[0].Description)) } fmt.Printf("Temperature: %.2f°C\n", weather.Main.Temp) fmt.Printf("Humidity: %d%%\n\n", weather.Main.Humidity) }
Пояснение к коду:
Функция выводит название города, описание погоды, температуру и влажность. Для аккуратного форматирования используется
fmt.Printf.С помощью
strings.Titleописание погоды приводится к красивому виду с заглавной буквы.
Эта функция завершает наш проект CLI-приложения прогноза погоды на Go — теперь пользователь получает понятную и полезную информацию о погоде прямо в терминале.
Шаг 5: Тестирование и запуск приложения
Перед тем как завершить работу, давайте протестируем приложение. Вот как запустить ваше CLI-приложение погоды на Go:
Установите API-ключ в переменную окружения:
Для Linux/Mac:
export OPENWEATHER_API_KEY=your_api_key_here
Для Windows (Command Prompt):
set OPENWEATHER_API_KEY=your_api_key_here
Запустите приложение, передав название города:
go run main.go London
Если вы не передадите название города, приложение предложит ввести его вручную.
Вы должны увидеть что-то вроде этого:
Weather for London: Description: Clear Sky Temperature: 15.00°C Humidity: 67%
Поздравляем! Вы успешно создали CLI-приложение погоды на Go. Теперь ваша программа умеет получать и отображать актуальную информацию о погоде по запросу пользователя.
Полный исходный код
Для удобства ниже приведён полный исходный код CLI-приложения погоды на Go:
Weather App
// main.go package main import ( "bufio" "encoding/json" "fmt" "io/ioutil" "net/http" "os" "strings" ) // WeatherData — структура под JSON-ответ OpenWeatherMap. type WeatherData struct { Name string `json:"name"` Main struct { Temp float64 `json:"temp"` Humidity int `json:"humidity"` } `json:"main"` Weather []struct { Description string `json:"description"` } `json:"weather"` } // getWeatherData получает данные о погоде для указанного города. func getWeatherData(city string, apiKey string) (*WeatherData, error) { // Формируем URL API. Используем метрическую систему (градусы Цельсия). url := fmt.Sprintf("http://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric", city, apiKey) // Отправляем HTTP-запрос. resp, err := http.Get(url) if err != nil { return nil, fmt.Errorf("failed to make request: %v", err) } defer resp.Body.Close() // Проверяем, что запрос прошёл успешно. if resp.StatusCode != http.StatusOK { bodyBytes, _ := ioutil.ReadAll(resp.Body) return nil, fmt.Errorf("error: received status code %d: %s", resp.StatusCode, string(bodyBytes)) } // Читаем тело ответа. bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %v", err) } // Декодируем JSON в структуру WeatherData. var weather WeatherData err = json.Unmarshal(bodyBytes, &weather) if err != nil { return nil, fmt.Errorf("failed to decode JSON: %v", err) } return &weather, nil } // displayWeatherData выводит информацию о погоде в удобном для пользователя формате. func displayWeatherData(weather *WeatherData) { fmt.Printf("\nWeather for %s:\n", weather.Name) if len(weather.Weather) > 0 { fmt.Printf("Description: %s\n", strings.Title(weather.Weather[0].Description)) } fmt.Printf("Temperature: %.2f°C\n", weather.Main.Temp) fmt.Printf("Humidity: %d%%\n\n", weather.Main.Humidity) } func main() { // Читаем API-ключ из переменной окружения. apiKey := os.Getenv("OPENWEATHER_API_KEY") if apiKey == "" { fmt.Println("Error: Please set the OPENWEATHER_API_KEY environment variable.") os.Exit(1) } // Проверяем, передано ли название города в аргументах командной строки. var city string if len(os.Args) > 1 { city = strings.Join(os.Args[1:], " ") } else { // Запрашиваем у пользователя название города, если аргумент не указан. fmt.Print("Enter the city name: ") reader := bufio.NewReader(os.Stdin) input, err := reader.ReadString('\n') if err != nil { fmt.Println("Error reading input:", err) return } city = strings.TrimSpace(input) } // Получаем данные о погоде. weather, err := getWeatherData(city, apiKey) if err != nil { fmt.Println("Error fetching weather data:", err) return } // Отображаем данные о погоде. displayWeatherData(weather) }
Русскоязычное Go сообщество

Друзья! Эту статью перевела команда «Go for Devs» — сообщества, где мы делимся практическими кейсами, инструментами для разработчиков и свежими новостями из мира Go. Подписывайтесь, чтобы быть в курсе и ничего не упустить!
Итоги
Создание CLI-приложения погоды на Go — это не только интересно, но и отличный способ прокачать навыки программирования. Вы научились настраивать проект, отправлять HTTP-запросы, парсить JSON и делать удобный инструмент для командной строки. Продолжая работу с Go, подумайте о расширении проекта, например:
Кэширование данных о погоде для быстрого доступа.
Поддержка нескольких городов в одном запросе.
Улучшенная обработка ошибок и логирование.
Надеюсь, вам понравился этот туториал. Дальше — экспериментируйте, дорабатывайте и, возможно, поделитесь своей версией CLI-приложения погоды с коллегами.
Удачного кодинга и пусть погода всегда радует!)
