---
title: "Справка: кастомизация help и usage"
description: "Cobra help кастомизация: SetHelpTemplate и SetUsageTemplate, функция SetHelpFunc, поля Long и Example, секции usage и --help подкоманд. Разбираем на примерах."
course: "Cobra: CLI-приложения на Go"
url: "https://golangmaster.ru/courses/cobra/lessons/12-help-usage/"
published: "2026-09-19"
updated: "2026-09-21"
minutes: 18
---

# Справка: кастомизация help и usage

*Курс «Cobra: CLI-приложения на Go», урок 12 из 25. ~18 минут. Обновлено 21.09.2026. Источник: https://golangmaster.ru/courses/cobra/lessons/12-help-usage/*

Cobra help кастомизация сводится к трём точкам входа: шаблон SetHelpTemplate, шаблон SetUsageTemplate и функция SetHelpFunc, а содержимое страницы складывают поля Long и Example. Разберём, чем help отличается от usage, как собрать страницу справки под свою утилиту и как переопределить вывод для одной подкоманды, не трогая остальные.

Пользователь, открывший вашу утилиту впервые, делает одно и то же: печатает --help и за десять секунд решает, разбираться дальше или закрыть терминал. За эти десять секунд отвечает не код команды, а страница справки, и у Cobra она собрана из двух слоёв. Первый слой — содержимое: поля Short, Long и Example, которые вы заполняете у каждой команды. Второй — форма: два Go-шаблона, HelpTemplate и UsageTemplate, раскладывающие это содержимое по экрану. Пока утилита маленькая, дефолтная страница выглядит прилично, и трогать её не нужно. Но как только справка перестаёт вмещать нужное — пример с флагами, секция про переменные окружения, особый формат для одной команды — начинается кастомизация. Пройдём оба слоя по порядку: сначала поля, из которых складывается текст страницы, затем шаблоны, задающие ей форму, и в конце — функция SetHelpFunc, заменяющая рендеринг целиком.

### Две страницы: help и usage

У каждой команды в Cobra две страницы, и это разные тексты. Usage — выжимка: строка использования UseLine, алиасы, список доступных подкоманд, локальные и глобальные флаги. Help — то, что печатается по флагу --help и по команде help: сначала абзац Long, затем Example, а в конце — usage-страница целиком. Из этого устройства следует главное правило кастомизации: содержимое пишем в поля, а не в шаблоны — Long и Example попадают на страницу сами, шаблоны нужны, когда не устраивает раскладка. Usage чаще всего видит расстроенный пользователь: при ошибке разбора флагов Cobra печатает сообщение и следом usage-страницу, и простыня флагов в этот момент скорее мешает найти саму ошибку — как её убрать, разбирается в уроке про ошибки и коды выхода. Отрендеренную usage можно получить и из кода: метод UsageString() возвращает её строкой, чем пользуются и кастомные шаблоны, и тесты.

### Long и Example: содержимое страницы

```go
var serveCmd = &cobra.Command{
        Use:   "serve [каталог]",
        Short: "Запустить сервер заметок",
        Long: `Запускает HTTP-сервер, который раздаёт заметки из каталога.
Порт и каталог переопределяются флагами; конфиг
читается из текущего каталога.`,
        Example: `  notes serve                       # текущий каталог
  notes serve ~/notes --port 9000
  notes serve --open                # сразу открыть браузер`,
        RunE: func(cmd *cobra.Command, args []string) error {
                return startServer(cmd, args)
        },
}
```

Long — абзац для страницы help: не дублируйте Short дословно, здесь место для деталей, которых не видно в списке команд. Example — многострочная строка с реальными вызовами; отступ в два пробела задаёт выравнивание, как в справках kubectl и gh. Оба поля дефолтный шаблон печатает сам — пока они заполнены, в шаблоны лезть не нужно.

### Проверка: пустой Long

**Вопрос:** У serveCmd не заполнено поле Long, Short задан. Что напечатает notes serve --help?

- ✅ Абзац из Short, затем usage-страница
- Пустое место вместо описания, затем usage
- Справка не откроется: пустой Long — ошибка
- Cobra подставит Use вместо описания

Дефолтный шаблон help берёт конструкцию or .Long .Short: при пустом Long на страницу уходит Short. Плохо это не ошибкой, а скудостью: Short писался под список команд, а не под страницу справки, поэтому Long стоит заполнять хотя бы у команд с флагами.

### Кастомизация help: шаблон SetHelpTemplate

Шаблон help — обычный text/template из стандартной библиотеки: в двойных фигурных скобках доступны поля команды, и на них можно собрать что угодно. Минимальная осмысленная замена дефолту — SetHelpTemplate с телом из описания и usage: {{.Long}}, пустая строка, {{.UsageString}}. В шаблоне доступны .Long, .Short, .Example, .CommandPath, .UseLine, .Runnable, флаги через .LocalFlags и .InheritedFlags, а из функций — rpad, gt, eq и trimTrailingWhitespaces, которыми пользуется и дефолтный шаблон. Важная деталь механики: шаблон ищется не только на самой команде. Не нашли у подкоманды — Cobra поднимается по дереву и берёт шаблон ближайшего предка, у которого он задан; установили на корне — получили для всего дерева сразу. И следите за концом шаблона: печатается ровно то, что в нём написано, включая финальный перенос строки, — без него справка прилипнет к следующему приглашению терминала.

### SetHelpTemplate с секцией примеров

```go
func init() {
        rootCmd.SetHelpTemplate(`{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}

{{end}}{{if .HasExample}}Примеры:
{{.Example}}

{{end}}{{.UsageString}}`)
}
```

Шаблон начинается как дефолтный — or .Long .Short с обрезкой хвостовых пробелов, — затем идёт своя секция «Примеры:», печатающаяся только при заполненном Example, и в конце UsageString со списком команд и флагов. Пустые строки между секциями набраны руками: шаблон ничего не добавляет сам, поэтому переводы строк — часть вашего контракта с пользователем.

### Шаблон, который печатает один Long

```go
rootCmd.SetHelpTemplate("{{.Long}}")

// notes serve --help
// Long и Example у serveCmd заполнены
```

**Что выведет программа?**

- ✅ Только абзац Long — без примеров и без usage
- Long и Example: примеры входят в Long
- Long и usage-страница: usage добавляется всегда
- Ошибка: шаблон help обязан печатать UsageString

Шаблон исполняется буквально: напечатано будет только то, что в нём перечислено. Example и usage в шаблон не попали — пользователь увидит одно описание, да ещё без перевода строки в конце, потому что финального переноса в шаблоне нет. Так страница справки тихо беднеет после «небольшой чистки».

### Usage-шаблон: SetUsageTemplate и секции

Usage-шаблон устроен плотнее: дефолт собирает строку использования, алиасы, примеры, доступные команды, флаги, глобальные флаги и дополнительные темы помощи — каждая секция через своё условие {{if}}. Кастомизация здесь обычно точечная: русифицировать заголовок Available Commands, спрятать секцию Additional help topics, добавить в конец строку со ссылкой на документацию. Механика наследования та же, что у help-шаблона: SetUsageTemplate на корне действует на всё дерево, а отдельная команда со своим шаблоном переопределяет только себя. Совсем заменить рендеринг функцией можно методом SetUsageFunc — она принимает func(*cobra.Command) error и пригодится, когда странице нужно то, чего шаблоном не выразить, например вывод через внешнюю программу. На практике функций хватает одному проценту утилит: сначала пробуйте шаблон, и только упершись в его пределы — SetUsageFunc.

### Свой usage-шаблон по-русски

```go
rootCmd.SetUsageTemplate(`Usage:{{if .Runnable}}
  {{.UseLine}}{{end}}

Доступные команды:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}

Флаги:
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}
`)
```

Упрощённый usage: строка использования, команды с русским заголовком и локальные флаги. Range по .Commands с проверкой IsAvailableCommand оставляет видимыми только настоящие команды плюс help, rpad выравнивает имена по общей ширине. За основу берите полный дефолтный шаблон из исходников своей версии Cobra — он длиннее и включает глобальные флаги и темы помощи.

### SetHelpFunc: справка под полный контроль

Когда шаблонов мало, остаётся функция. SetHelpFunc принимает func(*cobra.Command, []string) и полностью забирает рендеринг: Cobra больше ничего не печатает, всё на вас — хоть JSON для скриптов, хоть вывод через пейджер вроде less, хоть запрос к внешней программе. Аргументы — сама команда и хвост, который пользователь дописал после слова help: вызов notes help serve принесёт в функцию serve. Внутри принято печатать через cmd.OutOrStdout(): при обычном запуске это stdout, а в тестах вывод перехватывается буфером — им же мы будем ловить справку в уроке про тестирование. Наследование работает и здесь: HelpFunc ищется по дереву вверх, и функция корня отрисует справку всем подкомандам, у которых своей нет. Скажу честно, как о рабочем опыте: в девяти проектах из десяти хватает Long, Example и одного шаблона, а SetHelpFunc остаётся лазейкой на особые случаи — держите её в голове, но не открывайте без причины.

### SetHelpFunc: своя функция справки

```go
rootCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
        out := cmd.OutOrStdout()
        if cmd.Long != "" {
                fmt.Fprintln(out, cmd.Long)
        } else {
                fmt.Fprintln(out, cmd.Short)
        }
        if cmd.Example != "" {
                fmt.Fprintf(out, "
Примеры:
%s
", cmd.Example)
        }
        fmt.Fprint(out, cmd.UsageString())
})
```

Функция повторяет дефолтную логику в миниатюре: описание с подстановкой Short, свои «Примеры», usage в конце. Вся печать через OutOrStdout — справка уважает перенаправление и тестовые буферы. Обратите внимание: функция получает указатель на конкретную команду, поэтому никакой хардкод «описания корня» внутри недопустим — читайте cmd.

### Проверка: чья функция справки

**Вопрос:** Справку рендерит функция, заданная через rootCmd.SetHelpFunc. У serveCmd собственной help-функции нет. Что произойдёт при notes serve --help?

- ✅ Справку напечатает функция корня, получив указатель на serveCmd
- Cobra напечатает дефолтную справку: функции не наследуются
- Справка не напечатается: функция корня не видит подкоманды
- Вызов упадёт: нужна функция и на подкоманде

HelpFunc, HelpTemplate и UsageTemplate ищутся у команды, затем у родителей до корня. Функция корня получит указатель именно на serveCmd и напечатает её поля — поэтому внутри нельзя полагаться на то, что cmd окажется корнем.

### Флаг --help у каждой подкоманды

Флаг -h/--help не объявляется руками: Cobra добавляет его каждой команде сама, через InitDefaultHelpFlag, в момент выполнения. Поэтому notes serve --help показывает справку именно serve: её Long, её Example, её флаги, а флаги корня попадают в отдельную секцию Global Flags. Help-команда тоже строится автоматически, и notes help serve приводит к той же странице, что и notes serve --help, — разница только в привычке. Для --help не выполняется ни Run, ни хуки из следующего урока: проверка флага случается раньше, поэтому справка открывается мгновенно даже у тяжёлых команд, и звать её из скриптов безопасно. Если понадобится своё поведение помощи, команду help можно подменить через SetHelpCommand — но это экзотика, и в девяти случаях из десяти штатного флага достаточно.

> **Шаблон, который съел примеры.** Самая коварная правка справки — SetHelpTemplate с телом только из {{.UsageString}}: страница выглядит нормально, команды и флаги на месте, только Long и Example исчезли. Замечают это через месяц, когда в issue спрашивают, куда делись примеры. Вторая ловушка — незакрытая {{if}} или опечатка в поле: ошибка вылезет не при компиляции, а в рантайме при каждом вызове --help, и пользователь вместо справки увидит сообщение о template-ошибке. После любой правки шаблона соберите утилиту и прогоните --help для корня и пары подкоманд руками — песочница терминальный вывод не эмулирует, здесь нужен локальный Go.

### Чек-лист справки перед релизом

1. Long есть у каждой команды с флагами; Short описывает команду одним предложением и не повторяет Long дословно.
2. Example показывает два-три реальных вызова, начиная с самого частого сценария.
3. --help проверен на трёх уровнях: корень, подкоманда, вложенная подкоманда; отдельно — вызов notes help serve.
4. Перенаправление вывода не ломает справку: она уходит через OutOrStdout, а не печатается мимо stdout.
5. Правка шаблона не тронула автодополнение и команду help — они живут отдельно от шаблонов.

### help и usage рядом

|  | help | usage |
| --- | --- | --- |
| Когда печатается | по --help/-h и команде help | после ошибки флагов и внизу help-страницы |
| Состав | Long или Short, Example, usage целиком | UseLine, алиасы, команды, флаги |
| Кастомизация | SetHelpTemplate и SetHelpFunc | SetUsageTemplate и SetUsageFunc |
| Наследование | у ближайшего предка с шаблоном или функцией | то же самое |
| Доступ из кода | cmd.Help() печатает страницу | cmd.UsageString() возвращает строкой |

### Соберите шаблон и описание

Впишите название шаблонного метода и поле длинного описания.

```go
rootCmd.Set___Template("{{.Long}}\n\n{{.UsageString}}")

var serveCmd = &cobra.Command{
        Use:   "serve",
        Short: "Запустить сервер заметок",
        ___:   "Длинное описание сервера с деталями конфига",
}
```

Подсказка: Метод называется SetHelpTemplate, а поле длинного описания — Long (Short подставляется только при пустом Long).

Правильные ответы в пропусках: `Help`, `Long`

### Соберите SetHelpFunc из шести строк

Расставьте: переменная корня, начало функции, печать описания, печать usage, закрытие функции, регистрация.

Правильный порядок строк:

1. `var rootCmd = &cobra.Command{Use: "notes"}`
2. `func customHelp(cmd *cobra.Command, args []string) {`
3. `  fmt.Fprintln(cmd.OutOrStdout(), cmd.Long)`
4. `  fmt.Fprint(cmd.OutOrStdout(), cmd.UsageString())`
5. `}`
6. `func init() { rootCmd.SetHelpFunc(customHelp) }`

### Карточки: шаблоны и функции справки

- **HelpTemplate** — Шаблон страницы --help: дефолт печатает or .Long .Short, затем Example и UsageString. Задаётся SetHelpTemplate и наследуется от ближайшего предка.
- **UsageTemplate** — Шаблон usage-страницы: UseLine, алиасы, команды, флаги. Печатается после ошибки флагов и внизу help; SetUsageTemplate на корне покрывает всё дерево.
- **SetHelpFunc** — Полная замена рендеринга справки функцией func(*cobra.Command, []string). Печатайте через cmd.OutOrStdout() и читайте cmd — функция получает конкретную команду.
- **Long и Example** — Содержимое справки: Long — абзац для страницы help, при пустом подставляется Short; Example — многострочный список реальных вызовов.
- **UsageString()** — Возвращает отрендеренную usage-страницу строкой: вставка в свой шаблон, тесты, справка в чужом формате.
- **SetUsageFunc** — Функция func(*cobra.Command) error, полностью заменяющая рендеринг usage. Нужна редко: сначала пробуйте SetUsageTemplate.

### Что дальше

Страница справки собрана, и в следующем уроке про [хуки PreRun и PostRun](/courses/cobra/lessons/13-hooks-prerun/) мы переходим к тому, что происходит вокруг выполнения команды: цепочка PersistentPreRunE → PreRunE → RunE → PostRunE и знаменитая ловушка наследования PersistentPreRun. Справка — идеальный кандидат на тест: в уроке про [тестирование команд](/courses/cobra/lessons/20-testirovanie-cobra/) вывод --help ловится буфером и сравнивается с ожидаемым, так что правки шаблона перестанут быть слепыми. Обзор всех тем курса — на странице [Cobra](/courses/cobra/). И напоминание про среду, уже знакомое по другим урокам курса: шаблоны исполняются только живой утилитой, поэтому соберите проект локально, вызовите --help для корня и пары подкоманд и прочитайте результат своими глазами раньше, чем это сделают пользователи.

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

- Справка состоит из двух слоёв: содержимое в полях Long и Example, форма — в шаблонах HelpTemplate и UsageTemplate.
- Help печатается по --help и команде help; usage показывается после ошибок флагов и внизу help-страницы.
- Пустой Long подменяется Short — заполняйте Long хотя бы у команд с флагами.
- SetHelpTemplate на корне действует на всё дерево: шаблон ищется у ближайшего предка с заданным значением.
- UsageString() возвращает usage строкой — удобно для своих шаблонов и тестов.
- SetHelpFunc заменяет рендеринг целиком; вся печать — через cmd.OutOrStdout().
- После правки шаблона проверяйте --help локально: ошибка шаблона вылезает только в рантайме.

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

Заполните Long и Example для трёх команд своей утилиты, затем замените заголовок Available Commands на «Доступные команды» через SetUsageTemplate. Добавьте секцию «Примеры:» в SetHelpTemplate так, чтобы она печаталась только при непустом Example. Соберите проект, откройте --help для корня и двух подкоманд и проверьте, что ни одна секция не потерялась.

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

### Как изменить заголовок Available Commands в Cobra?

Задайте свой SetUsageTemplate на корне: скопируйте дефолтный шаблон из исходников Cobra вашей версии и замените текст заголовка внутри range по .Commands. Дефолтный шаблон меняется между версиями, поэтому правьте копию, а не пересобирайте с нуля.

### Чем SetHelpFunc отличается от SetHelpTemplate?

Шаблон — это text/template, который Cobra исполняет за вас; функция — полный контроль: она вызывается вместо любого рендеринга и печатает что угодно, включая пейджер или JSON. Для большинства утилит хватает шаблона, функция нужна для особых форматов вывода.

### Почему --help подкоманды показывает Short вместо длинного описания?

Поле Long у этой подкоманды пустое: дефолтный шаблон берёт or .Long .Short. Заполните Long — и страница подкоманды получит полноценное описание, не трогая Short в списке команд родителя.
