Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 1 из 25 ~16 мин +50 XP

Знакомство с Cobra: зачем нужен CLI-фреймворк

Cobra — go-фреймворк для командной строки: на нём написаны kubectl, Hugo и GitHub CLI, и в этом уроке разберём, зачем он нужен, из чего состоит консольная утилита и чем Cobra отличается от стандартного пакета flag.

Содержание урока · 12 разделов

Откройте терминал и наберите kubectl get pods -n prod --watch. За долю секунды kubectl разберёт эту строку: get — подкоманда, pods — её аргумент, -n и --watch — флаги, один со значением, другой без. Потом он напечатает справку, если вы ошиблись, дополнит имя подкоманды по Tab и молча проглотит любой порядок флагов. Ничего из этого не имеет отношения к Kubernetes — это работа CLI-фреймворка. Написать разбор строки руками на os.Args можно: срез строк, switch по первому элементу, вложенный switch внутри него. Но к третьей подкоманде в коде заводится собственный мини-парсер, к пятой — самодельная справка, а к седьмой вы ловите себя на том, что пишете kubectl в миниатюре вместо своей задачи. Cobra закрывает именно эту рутину — и сейчас разберём, как она устроена и зачем её вообще отделять от бизнес-логики.

Что такое Cobra: go-библиотека CLI и её история#

Cobra — CLI-фреймворк для Go: библиотека, которая берёт на себя разбор командной строки, дерево подкоманд, справку и автодополнение. Написал её Стив Франсия (Steve Francia, ник spf13) в 2013 году — тот же человек за год до этого создал генератор сайтов Hugo, а позже руководил developer relations в Docker и Google. Проект годами живёт в версии 1.x: API стабилен настолько, что примеры из туториалов пятилетней давности компилируются без правок. Код лежит в github.com/spf13/cobra, а рядом живёт Viper — библиотека конфигурации от того же автора; в реальных CLI они часто ходят парой, и в этом курсе мы до неё тоже дойдём. За эти годы Cobra стала стандартом де-факто: когда в Go-команде встаёт вопрос «как делать CLI», ответ по умолчанию — она же, и собеседования спрашивают ровно про это. У Cobra две ипостаси, которые новички часто путают: сама библиотека и генератор каркасов cobra-cli — отдельная утилита, которая по одной команде создаёт готовый проект. С генератором познакомимся во втором уроке, пока важен словарь.

Кто написан на Cobra#

  • Kubernetes — kubectl целиком построен на Cobra: get, apply, describe и десятки других подкоманд
  • GitHub CLI (gh) — pr, issue, repo: три уровня дерева команд на одном фреймворке
  • Hugo — генератор статических сайтов, родной брат Cobra: автор у обоих один и тот же
  • Docker CLI — клиент docker переехал на Cobra вместе с системой плагинов
  • rclone, etcd, Twitch CLI — список проектов на сайте Cobra давно перевалил за сотню

Анатомия CLI: команда, подкоманда, флаг, аргумент#

Возьмём строку посложнее: gh pr create --title «Правки в API» --base main 42. Слева направо: gh — исполняемый файл, то, что нашлось в PATH; pr — подкоманда первого уровня; create — подкоманда второго уровня; 42 — позиционный аргумент, его смысл определяется только местом в строке; --title и --base — флаги со значениями, их порядок можно менять как угодно. Этот словарь — фундамент курса, проговорим его чётко. Команды задают глагол: что делать. Аргументы — объект: над чем делать. Флаги — настройки: как именно делать. Сильные консольные утилиты соблюдают это правило почти религиозно: в git commit -m «сообщение» команда — commit, флаг -m несёт текст. Если пользователь вашей утилиты должен угадывать, что значит третий параметр подряд, — это баг дизайна, а не сложность предметной области.

Минимальная программа на Cobra, которую будем разбирать

GO
package main

import (
        "fmt"
        "os"

        "github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
        Use:   "hello",
        Short: "Приветствие из первого урока",
        Run: func(cmd *cobra.Command, args []string) {
                fmt.Println("Привет, CLI!")
        },
}

func main() {
        if err := rootCmd.Execute(); err != nil {
                os.Exit(1)
        }
}

Вся программа — одна переменная rootCmd типа *cobra.Command. Поле Use задаёт имя команды, Short — однострочное описание для справки, Run — функцию, которая выполнится при запуске. Execute() читает os.Args, находит нужную команду и вызывает её Run; при ошибке возвращается error, и os.Exit(1) отдаёт скриптам код выхода, отличный от нуля.

Что общего у kubectl, Hugo и gh#

Сядьте за любой из этих инструментов — и первые минуты пройдёте без документации, потому что все они ведут себя одинаково. gh --help печатает список подкоманд с однострочными описаниями; gh pr --help разворачивает подробности уже про pr. hugo server --port 1313 понимает флаг и до, и после имени подкоманды. kubectl на опечатку отвечает подсказкой Did you mean this?. Это не копирование чужого стиля — это Cobra, у которой контракт пользователя встроен в библиотеку: справка генерируется на каждом уровне дерева, у флагов есть шорткаты (-n и --namespace — один и тот же флаг), шелл получает автодополнение через встроенную команду completion, версия печатается по --version. Пользователь вашей утилиты получит привычное поведение бесплатно, а вы выбросите из плана сорок разборов os.Args. Заодно унифицируется мелочь, которую никто не любит писать руками: --version у корня, поведение при пустом вызове, чтение конфига до первой команды. Каждый пункт по отдельности — полчаса работы и вечный спор «а как у нас принято?»; в Cobra они просто есть.

Cobra против пакета flag#

Стандартная библиотека Go умеет парсить флаги пакетом flag, и на одном уровне он хорош: определить flag.String, вызвать flag.Parse — готово. Ограничения всплывают сразу за этим уровнем. Дерева команд нет: подкоманды придётся перебирать вручную по os.Args и для каждой заводить свой FlagSet. Справка генерируется только списком флагов — ни однострочных описаний подкоманд, ни развёрнутых Long-текстов. Автодополнения и подсказок при опечатках нет вообще. Нюанс, о котором забывают: под капотом Cobra работает не flag, а pflag — его форк с POSIX-семантикой: формы --flag=value, объединение шорткатов -abc в один вызов, флаги до и после позиционных аргументов. flag с этим справляется хуже. Если у вас уже есть код на flag, миграция обычно начинается с замены flag.String на cmd.Flags().String — семантика почти совпадает, ломаться нечему. Мой вывод после утилит на обоих: flag — для скриптов и инструментов с одной командой, Cobra — как только нарисовалась вторая подкоманда. Это не религия, а точка окупаемости: дерево и справка в Cobra описываются декларативно, руками — итеративно и со скрипом.

flag и Cobra: что приходится писать самому#

ЗадачаflagCobra
Дерево подкоманднет — только вручную по os.ArgsAddCommand и готовая маршрутизация
Справка --helpсписок флагов по умолчаниюгенерируется по Use, Short, Long, Example
Автодополнение bash/zshнетвстроенная команда completion
Подсказка при опечаткенетDid you mean this? из коробки
Хуки до и после командынетPreRun, PostRun и их персистентные версии
Привязка конфигурациинетштатная связка с Viper

Когда Cobra не нужна#

Честности ради: не каждая утилита заслуживает фреймворк. Если программа принимает пару флагов, у неё одна точка входа, а справка помещается в абзац README — берите flag или читайте os.Args напрямую: лишняя зависимость в go.mod не нужна. Мой водораздел такой: появилась вторая подкоманда или справка перестала влезать в одну строку — время Cobra. Вторая ситуация, где я обходился без неё, — утилиты внутри монорепозитория со своим запускачом и конфигом: там от CLI нужны только флаги, и flag хватает с запасом. Спорная часть: некоторые тянут Cobra и для однострочников ради красивой справки. Я так не делаю — сборка дольше, пользы ноль, — но если в команде есть готовый шаблон проекта, цена стремится к нулю, и тогда возражений нет.

Как устроен курс и что понадобится#

Курс практический: с третьего урока в голове держим один проект — CLI-менеджер задач, который к финалу обрастёт конфигами, цветным выводом и тестами. Одна оговорка про формат: браузерная песочница сайта исполняет чистый Go без файловой системы и os.Args, поэтому Cobra-код в уроках не запускается онлайн — примеры нужно гонять локально с установленным Go, а интерактивы в песочнице остаются разминкой на синтаксис. Если сам Go у вас пока на уровне «читал, но не писал», начните с базового курса: структуры, ошибки и пакеты понадобятся уже на второй неделе. И настройтесь на интерактивы в каждом уроке — тесты, пропуски и карточки засчитывают XP и заодно работают повторением: тезис, который не отложился, всплывёт в вопросе раньше, чем вы его забудете.

Проверка: анатомия командной строки

В вызове gh pr create --title «Правки» 42 что такое 42?

Проверка: flag или Cobra

Что из перечисленного умеет Cobra, но не умеет пакет flag?

Что напечатает программа без аргументов

Прочитайте код и выберите, что он выведет:

package main

import (
        "fmt"

        "github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
        Use:   "hello",
        Short: "Приветствие из первого урока",
        Run: func(cmd *cobra.Command, args []string) {
                fmt.Println("Привет, CLI!")
        },
}

func main() {
        rootCmd.Execute()
}

Восстановите минимальную Cobra-программу

Впишите имя пакета, путь импорта фреймворка, имя команды в Use и тип команды.

package import "github.com/spf13/" var rootCmd = &cobra.Command{ Use: "", Run: func(cmd *cobra., args []string) {}, } func main() { rootCmd.Execute() }

Соберите каркас из шести строк

Расставьте строки от объявления пакета до вызова Execute.

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Карточки: словарь CLI и Cobra

Термин

Cobra

нажмите, чтобы перевернуть
Определение

CLI-фреймворк для Go (2013, Стив Франсия): дерево команд, справка, автодополнение, хуки. Библиотека github.com/spf13/cobra.

1 / 6

Что дальше#

Во втором уроке поставим Cobra и сгенерируем первый проект: cobra-cli init, структура main.go и cmd/root.go, первый запуск. Третий урок — дерево команд: rootCmd, AddCommand и справка, ради которой всё затевалось. Потом пойдут флаги — локальные и персистентные, они заслуживают отдельного урока, потому что в CLI их больше всего. Финал курса — CLI-менеджер задач, куда сложится всё пройденное. Пока подготовьте площадку: убедитесь, что go version отвечает, и освободите вечер — с четверти часа на второй урок уйдёт только на установку.

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

Коротко: что запомнить

  • Cobra — CLI-фреймворк Go: дерево команд, справка, автодополнение и хуки в одной библиотеке.
  • На Cobra написаны kubectl, Hugo, GitHub CLI и Docker CLI — у всех один пользовательский контракт.
  • Словарь курса: команда — глагол, аргумент — объект, флаг — настройка.
  • flag парсит флаги одной программы; Cobra добавляет дерево, справку, подсказки и completion, работая поверх pflag.
  • Cobra и cobra-cli — разные вещи: библиотека в каждом проекте, генератор — один раз на машину.
  • Для утилиты с парой флагов Cobra избыточна; моя точка входа — вторая подкоманда.
  • Код курса запускается локально: песочница сайта Cobra не исполняет.

Домашнее задание

Вспомните три CLI, которыми пользуетесь каждый день: git, docker, kubectl — что угодно. Для каждого выпишите две подкоманды, один позиционный аргумент и два флага, один со значением, другой без. Затем откройте справку каждой утилиты через --help и проверьте, что подкоманды показаны с однострочными описаниями. Этот словарь пригодится в четвёртом уроке, где будем решать, аргумент перед нами или флаг.

Личные заметкиПусто
Хранятся только в вашем браузере (Cobra · Знакомство с Cobra: зачем нужен CLI-фреймворк)

Вопросы и ответы по уроку

Что такое Cobra в Go простыми словами?

Библиотека, которая снимает с разработчика рутину консольной утилиты: разбор строки запуска, дерево подкоманд, справку --help, автодополнение и подсказки при опечатках. Вы описываете команды и пишете только их логику.

Чем Cobra лучше стандартного flag?

flag умеет парсить флаги одной программы. Cobra добавляет дерево подкоманд, многоуровневую справку, автодополнение для шеллов, хуки PreRun и PostRun, подсказки опечаток. Для утилиты с подкомандами разница огромна.

Нужно ли знать Go, чтобы пройти курс?

Да, на базовом уровне: функции, структуры, ошибки. Если это пока в стадии чтения, начните с курса «Go с нуля» — код Cobra-проектов опирается на структуры и методы с самых первых уроков.

Термины урока

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

Сравните с альтернативами

Практический вопрос после первых уроков: а почему именно эта библиотека? Мы разобрали конкурентов по одним критериям, с кодом одной задачи рядом и персональным подбором под ваши приоритеты.

Следующая ступень учебного пути

Bubble Tea25 уроков~10 чпрактика25 уроков уже доступны

Bubble Tea: TUI-приложения в терминале

Интерактивный курс Bubble Tea — TUI-фреймворка на Go: Elm-архитектура, bubbles, Lip Gloss, мышь и клавиатура. 25 уроков с примерами и итоговым приложением.

  • Понимать Elm-архитектуру: Model, Update, View, Init
  • Обрабатывать клавиатуру и мышь в терминале
  • Писать асинхронные операции через tea.Cmd, Batch и Sequence
  • Использовать bubbles: list, textinput, textarea, table, viewport, progress, spinner