Тема 04 · Аннотации типов и документация кода

Аннотации типов и документация кода · МДК.01.01 · разработка программных модулей

Глава 4.6

4.6

Документация кода:
какая она бывает

В этой главе разобрано, что называют документацией кода, какие пять её видов встречаются в проекте на Python, где каждый из них хранится и кто его читает. Отдельно разобрана разница между комментарием и докстрингом: выглядят они похоже и при этом попадают в разные места программы.

Категория
Понятия
Уровень
Начальный
Опирается на
Аннотации типов, главы 4.1–4.5
Зачем это знать
Различать виды документации и выбирать нужный

§1Что называют документацией кода

Документация кода — текст, который объясняет назначение программы и её частей и хранится вместе с исходным кодом. Её читатель — разработчик: тот, кто этот код вызывает, читает и изменяет. Инструкция для пользователя программы пишется отдельно и в исходники не попадает.

Чтобы вызвать функцию из соседнего модуля, нужно знать три вещи:

  1. что функция делает;
  2. что она принимает и какие значения допустимы;
  3. что она возвращает и что будет при неверных данных.

Аннотации из глав 4.1–4.5 закрывают часть этих вопросов: типы параметров и результата теперь записаны в подписи. Остальное аннотация не передаёт — что функция делает, какие значения из допустимого типа подходят, в каких единицах результат и какие ошибки возможны. Эти сведения пишут словами рядом с функцией, и редактор показывает их в месте вызова так же, как типы.

Проект, на котором идёт разбор

Работа продолжается на проекте «Отчёт кафе» из главы 4.1 — теперь со вторым архивом. В нём аннотации уже расставлены, как по итогам практики в главе 4.5, а описаний нет ни одного: их предстоит написать в этой части темы. Если практика по аннотациям сделана, можно продолжать в своей папке; если нет — скачайте второй архив.

  1. Распакуйте архив и откройте папку otchet-kafe-start в VS Code.
  2. Создайте окружение и установите зависимости: python3 -m venv .venvpy -m venv .venv, затем .venv/bin/pip install -r requirements.txt.venv\Scripts\pip install -r requirements.txt.
  3. Запустите проект: .venv/bin/python main.py.venv\Scripts\python main.py. В терминале появится отчёт по смене.
На полях: короткие команды в этой части

Дальше команды записаны коротко: ruff check app, python -c "…", python -m pytest -q. В таком виде они работают в терминале с активированным окружением — в начале строки стоит (.venv). Активация: source .venv/bin/activate.venv\Scripts\Activate.ps1 в PowerShell или .venv\Scripts\activate.bat в командной строке. Без активации перед командой пишут путь: .venv/bin/ruff check app.venv\Scripts\ruff check app.

VS Code с проектом «Отчёт кафе»: дерево файлов слева, main.py в редакторе, внизу терминал с напечатанным отчётом
Второй архив после запуска. Слева дерево: пакеты app, папка data с файлом смены, папка tests. В редакторе main.py: он вызывает load_orders, revenue_by_waiter и функции форматирования. Внизу в терминале — напечатанный отчёт: три официанта и итог 4 937,50 ₽.

§2Пять видов и их читатели

В проекте на Python встречаются пять видов текста о коде. Они не взаимозаменяемы: у каждого своё место в файлах и свой читатель.

ВидГде лежитКто читаетЧто отвечает
Комментарий Внутри функции, после знака # Тот, кто правит эту функцию Почему строка написана так
Докстринг Первой строкой модуля, класса или функции, в тройных кавычках Тот, кто вызывает функцию извне Что функция делает, что принимает, что возвращает
Аннотация типа В подписи функции: def f(x: int) -> str Редактор, проверщик типов, человек Какого типа значения допустимы
README Файл README.md в корне проекта Тот, кто впервые открыл репозиторий Что это за проект, как его запустить
Сгенерированный сайт Папка docs/, собирается программой Тот, кто пользуется библиотекой и в код не заходит Полный перечень функций с описаниями

Первые три вида лежат внутри файла с кодом и меняются вместе с ним. README лежит отдельным файлом в корне проекта и обновляется отдельным действием. Сайт собирается программой из докстрингов: свой текст в него не дописывают, правят исходники и собирают заново.

app/services/orders.py """Заказы смены: чтение и расчёты.""" докстринг модуля · первая строка файла import csv def load_orders(path: Path) -> list[Order]: """Читает заказы из файла смены.""" докстринг функции · сразу после def # имена приводим к одному виду сразу return [Order(**row) for row in read_rows(path)] оранжевым — докстринги: их читает тот, кто вызывает пунктиром — комментарий: его читает тот, кто правит README.md о проекте целиком: назначение, запуск, состав файлов docs/index.html собранный сайт: перечень функций с описаниями собирается программой из докстрингов, вручную не правится
Три вида лежат в одном файле: докстринг модуля первой строкой, докстринг функции сразу после def, комментарий внутри тела. Аннотации типов стоят в самой подписи. README лежит отдельным файлом в корне проекта. Сайт документации не пишут руками: его собирает программа из докстрингов, и стрелка идёт только в одну сторону.

Зачем это нужно в работе

  • Вызов функции без чтения её тела. Докстринг виден в подсказке редактора в момент вызова, поэтому проверять поведение по исходнику приходится реже.
  • Передача кода другому человеку. На защите вклада и при передаче модуля смежной команде задокументированный публичный интерфейс заменяет разбор кода построчно.
  • Проверка на стороне инструментов. Отсутствие докстринга у публичной функции проверяется программой и попадает в замечания к запросу на слияние так же, как ошибка форматирования.

§3Комментарий и докстринг: где они оказываются

Комментарий и докстринг записываются в одном файле и попадают в разные места программы. Комментарий интерпретатор отбрасывает при чтении файла: в работающей программе его нет. Докстринг сохраняется в самом объекте — в модуле, классе или функции — и доступен во время работы программы.

app/services/calculator.pyдва текста об одной функции
def calculate_average(grades: list[int]) -> float:
    """Считает среднюю оценку по списку.

    Args:
        grades: Оценки от 2 до 5, список не должен быть пустым.

    Returns:
        Среднее значение, округлённое до двух знаков.

    Raises:
        ValueError: Если список оценок пуст. Среднее по пустому списку
            не определено, поэтому нуль в этом случае не возвращается.
    """
    if not grades:
        raise ValueError("Список оценок пуст")
    # round вызывается один раз в конце: округление каждого
    # слагаемого по отдельности смещает результат
    return round(sum(grades) / len(grades), 2)

Строка в тройных кавычках — докстринг. Она обращена к тому, кто будет вызывать calculate_average из другого модуля: перечислено, что принимается, что возвращается и когда вместо результата будет ошибка. Слова Args:, Returns: и Raises: — разметка разделов; она разобрана в главе 4.8, здесь достаточно прочитать текст под ними. Две строки после знака # — комментарии. Они объясняют выбор внутри тела и нужны тому, кто станет эту функцию править.

Разница проверяется из программы: докстринг доступен через атрибут __doc__, комментария в объекте нет.

Терминалpython
>>> from app.services.calculator import calculate_average
>>> print(calculate_average.__doc__.splitlines()[0])
Считает среднюю оценку по списку.

Ассоциация: упаковка лекарства

В жизни

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

В коде

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

Где не совпадаетНадпись на коробке печатает завод один раз, и она не меняется. Докстринг правит тот же человек, который меняет функцию, и описание при этом можно забыть обновить. Поэтому докстринг исправляют в том же изменении, что и поведение.

§4Что берёт на себя имя и аннотация типа

Часть работы документации выполняют имя функции и аннотации типов, разобранные в главах 4.1–4.5. Имя calculate_average сообщает действие, аннотация list[int] -> float сообщает типы. Повторять это словами в докстринге не требуется.

Повтор подписи

"""Функция calculate_average принимает список целых чисел grades и возвращает число с плавающей точкой."""

→
То, чего в подписи нет

"""Считает среднюю оценку по списку. Пустой список приводит к ValueError, результат округляется до двух знаков."""

В докстринг идёт то, что из подписи не следует: смысл значения, ограничения на входные данные, поведение в исключительных случаях, единицы измерения. Например, что суммы в проекте хранятся в копейках, из аннотации int не видно, и это место для докстринга.

На полях: тест тоже документирует

Тест показывает поведение на конкретных данных: calculate_average([5, 4, 5, 3, 5]) == 4.40. Это точная запись ожидания, которую проверяет программа. Докстринг и тест закрывают разные потребности: по докстрингу понимают назначение, по тесту — точный результат на примере. В главе 4.8 разобран формат, который позволяет записать пример прямо в докстринг и проверять его запуском.

§5Документация, собранная в сайт

Автоматическая документация — набор HTML-страниц, который программа собирает из исходного кода проекта: проходит по модулям, находит функции и классы, забирает их докстринги и раскладывает по страницам с оглавлением и поиском. Так устроена, например, документация самого Python на сайте docs.python.org.

В Python для этого используется Sphinx — программа сборки документации, которой достаточно указать корень проекта и перечислить модули. Порядок работы такой:

Путь от докстринга до страницы

1 · Докстринг Описание лежит в функции, в тройных кавычках. пишет разработчик
2 · Настройка Указано, где лежат исходники и какой формат докстрингов используется. один раз на проект
3 · Сборка Программа читает модули и собирает HTML. команда в терминале
4 · Сайт Папка со страницами: оглавление, поиск, перечень функций. можно выложить на Pages

Шаги 2–4 разбираются в следующей теме. Здесь важен шаг 1: в сайт попадает то, что написано в докстрингах: восполнить недостающее описание сборщику неоткуда.

§6Правило документирования в этом курсе

Каждое описание правят вместе с кодом, поэтому описывать всё подряд не требуется. В курсе принято правило по границам модуля: описание обязательно там, где код вызывают снаружи.

Докстринг обязателен

Модуль пакета app/Первая строка файла: за что этот модуль отвечает.
Публичная функция и методВсё, что вызывается из другого модуля или из main.py.
КлассЧто представляет объект этого класса и какие у него атрибуты.
Функция, которая возбуждает исключениеРаздел с перечнем ошибок: по нему вызывающий код решает, что перехватывать.

Служебные функции с именем, начинающимся с подчёркивания, документируются одной строкой или остаются без докстринга: они вызываются только внутри своего модуля. Проверки, что это правило соблюдено, настраиваются программой — это разобрано в главе 4.10.

§7Частые вопросы

Обычно думаютХороший код понятен без документации, поэтому докстринги нужны только плохому коду.
На самом делеПонятный код отвечает на вопрос «как это работает». Докстринг отвечает на вопрос «что эта функция обещает вызывающему»: границы входных данных, единицы измерения, поведение при ошибке. Из тела функции это выясняется чтением, из докстринга — сразу.
Обычно думаютДокстринг — то же самое, что комментарий, просто в кавычках.
На самом делеКомментарий исчезает после чтения файла интерпретатором. Докстринг хранится в объекте, доступен через __doc__ и help(), показывается в подсказке редактора и попадает в собранную документацию.
Обычно думаютЕсли есть README, докстринги не нужны.
На самом делеREADME отвечает на вопросы о проекте целиком: назначение, установка, запуск. Описание каждой из двухсот функций в него не помещается, и читать его в момент вызова функции неудобно.
Обычно думаютДокументацию пишут в конце, когда код готов.
На самом делеОписание, написанное через месяц после кода, приходится восстанавливать чтением собственного кода. Докстринг пишется вместе с функцией и правится вместе с ней: тогда он совпадает с поведением.

§8Проверьте себя

Чем докстринг отличается от комментария по месту хранения?

Комментарий существует только в тексте файла: интерпретатор отбрасывает его при чтении, и в работающей программе комментария нет. Докстринг становится значением атрибута __doc__ у модуля, класса или функции, поэтому он доступен во время работы программы, через help() и в подсказке редактора.

В функции есть аннотации типов. Что после этого остаётся написать в докстринге?

То, чего в подписи нет: смысл значения и единицы измерения (например, что сумма хранится в копейках), ограничения на входные данные, поведение при пустом или недопустимом значении, перечень возбуждаемых исключений. Перечисление типов словами в докстринге дублирует подпись.

Какие виды документации обновляются вместе с кодом, а какие отдельно?

Комментарий, докстринг и аннотация лежат в том же файле и правятся вместе с функцией. README лежит отдельно и обновляется отдельным действием. Сайт документации не правится вручную: меняют докстринги в исходниках и собирают сайт заново.

Почему сборщик документации не может обойтись без докстрингов?

Сборщик берёт текст описаний из кода: находит функцию, её подпись и аннотации, а описание назначения брать ему неоткуда. Функция без докстринга попадёт на страницу одной подписью, поэтому качество собранного сайта равно качеству докстрингов.

У функции имя начинается с подчёркивания. Обязателен ли для неё докстринг по правилу курса?

Нет. Подчёркивание в начале имени означает, что функция служебная и вызывается внутри своего модуля. Для неё достаточно одной строки или комментария. Обязательны докстринги у модулей, классов и функций, которые вызывают снаружи.

§9Шпаргалка по главе

Комментарий # после кода в строке читает тот, кто правит в программе не хранится
Докстринг """первая строка объекта""" читает тот, кто вызывает хранится в __doc__
Аннотация def f(x: int) -> str только типы
README о проекте целиком назначение, запуск, состав
Сайт документации собирается из докстрингов Sphinx, следующая тема
Обязательно описывать модули пакета app/ публичные функции и классы возбуждаемые исключения

Итог главы

Документация кода — текст о назначении программы, который хранится вместе с исходниками. В проекте на Python её пять видов: комментарий внутри тела, докстринг у модуля, класса и функции, аннотация типа в подписи, README о проекте целиком и собранный программой сайт. Комментарий адресован тому, кто правит код, и в работающей программе его нет. Докстринг адресован тому, кто вызывает функцию, хранится в атрибуте __doc__ и попадает в подсказку редактора и в собранную документацию. Имя и аннотации сообщают действие и типы, поэтому в докстринг идут ограничения, единицы измерения и поведение при ошибках. В курсе описания обязательны для модулей пакета, публичных функций, классов и мест, где возбуждаются исключения. В следующей главе разобрано, как докстринг устроен: где он должен стоять, как его прочитать из программы и какие правила задаёт стандарт PEP 257.

Откуда взяты факты
  1. Хранение докстринга в атрибуте __doc__ и правила его размещения — учебник Python, раздел о строках документации.
  2. Стандарт оформления — PEP 257, Docstring Conventions.
  3. Сборка документации из исходного кода — сайт Sphinx.
4.6

Документация кода:
какая она бывает

В этой главе разобрано, что называют документацией кода, какие пять её видов встречаются в проекте на Go, где каждый из них хранится и кто его читает. Отдельно разобрана разница между обычным комментарием и комментарием документации: записываются они одинаково, через //, а отличаются только местом в файле.

Категория
Понятия
Уровень
Начальный
Опирается на
Типы в Go, главы 4.1–4.5
Зачем это знать
Различать виды документации и выбирать нужный

§1Что называют документацией кода

Документация кода — текст, который объясняет назначение программы и её частей и хранится вместе с исходным кодом. Её читатель — разработчик: тот, кто этот код вызывает, читает и изменяет. Инструкция для пользователя программы пишется отдельно и в исходники не попадает.

Чтобы вызвать функцию из соседнего пакета, нужно знать три вещи:

  • что функция делает;
  • что она принимает и какие значения допустимы;
  • что она возвращает и в каких случаях вместо результата будет ошибка.

Подпись функции из глав 4.1–4.5 закрывает часть этих вопросов: типы параметров и результатов в Go записаны всегда. Остального подпись не передаёт — что функция делает, какие значения из допустимого типа подходят, в каких единицах результат, когда возвращается ошибка и какая именно. Эти сведения пишут словами перед функцией, и редактор показывает их в месте вызова вместе с подписью.

Проект, на котором идёт разбор

Работа продолжается на проекте «Отчёт кафе» из главы 4.1 — на втором архиве. Код в нём рабочий и собирается, а комментариев документации нет ни одного: их предстоит написать в этой части темы. Если практика 4.5 сделана, можно продолжать в своей папке: исправленный проект совпадает со вторым архивом.

  1. Распакуйте архив и откройте папку otchet-kafe-go-start в VS Code — ту, в которой лежит go.mod.
  2. Откройте терминал редактора и запустите проект: go run .. В терминале появится отчёт по смене. Команды Go одинаковы во всех системах, окружение создавать не нужно.
VS Code со вторым архивом Go: слева дерево с папками data и internal, в редакторе main.go, внизу в терминале отчёт по смене
Второй архив после запуска. Слева дерево: свёрнутые папки data с файлом смены и internal с четырьмя пакетами, ниже go.mod, main.go и README.md. В редакторе main.go: он вызывает LoadOrders, RevenueByWaiter и функции форматирования. Внизу в терминале — напечатанный отчёт: три официанта и итог 4 937,50 ₽.

§2Пять видов и их читатели

В проекте на Go встречаются пять видов текста о коде. Они не взаимозаменяемы: у каждого своё место в файлах и свой читатель.

ВидГде лежитКто читаетЧто отвечает
Комментарий Внутри функции, после // Тот, кто правит эту функцию Почему строка написана так
Комментарий документации Строки // вплотную над package, func, type, var, const Тот, кто вызывает функцию из другого пакета Что функция делает, что принимает, что возвращает
Тип в подписи В подписи функции: func F(x int) string Компилятор, редактор, человек Какого типа значения допустимы
README Файл README.md в корне проекта Тот, кто впервые открыл репозиторий Что это за проект, как его запустить
Сайт документации Страницы, которые собирает программа pkgsite или сайт pkg.go.dev Тот, кто пользуется пакетом и в код не заходит Полный перечень пакетов, функций и типов с описаниями

Первые три вида лежат внутри файла с кодом и меняются вместе с ним. README лежит отдельным файлом в корне проекта и обновляется отдельным действием. Сайт собирается программой из комментариев документации: свой текст в него не дописывают, правят исходники и собирают заново.

internal/services/calculator.go // Package services — расчёты. комментарий пакета · над package package services // CalculateAverage считает среднюю… комментарий функции · вплотную над func func CalculateAverage(grades []int) … // Сумма переводится в float64… return math.Round(…), nil оранжевым — документация: её читает тот, кто вызывает пунктиром — комментарий: его читает тот, кто правит README.md о проекте целиком: назначение, запуск, состав пакетов pkgsite · go doc собранные страницы: пакеты, функции и типы с описаниями собирается программой из комментариев, вручную не правится
Три вида лежат в одном файле: комментарий пакета над строкой package, комментарий функции вплотную над func, обычный комментарий внутри тела. Типы стоят в самой подписи. README лежит отдельным файлом в корне проекта. Страницы документации не пишут руками: их собирает программа из комментариев документации, и стрелка идёт только в одну сторону.

Зачем это нужно в работе

  • Вызов функции без чтения её тела. Комментарий документации виден в подсказке редактора в момент вызова, поэтому проверять поведение по исходнику приходится реже.
  • Передача кода другому человеку. Когда пакет передают другому разработчику или смежной команде, описания экспортируемых имён избавляют от разбора кода построчно.
  • Проверка на стороне инструментов. Отсутствие комментария у экспортируемого имени находит программа revive. Если её запуск добавлен в проверки запроса на слияние, замечание попадает туда так же, как ошибка сборки.

§3Комментарий и комментарий документации

В Python докстринг и комментарий записываются по-разному: строка в кавычках и строка после #. В Go отдельной записи для документации нет. И то и другое — строки, начинающиеся с //. Комментарием документации строку делает только место:

  • комментарий стоит перед объявлением верхнего уровня — package, func, type, var или const;
  • между последней строкой комментария и объявлением нет пустой строки.

Такой комментарий называют комментарием документации (doc comment). Всё остальное — комментарии внутри тела функции, комментарии, отделённые пустой строкой, — обычные комментарии: инструменты документации их пропускают. Оба вида видны в функции CalculateAverage из третьего архива:

internal/services/calculator.goдва текста об одной функции
// CalculateAverage считает среднюю оценку по списку и округляет
// её до двух знаков после запятой.
//
// Для пустого списка возвращается [ErrNoGrades]: среднее по пустому
// списку не определено, поэтому нуль в этом случае не возвращается.
func CalculateAverage(grades []int) (float64, error) {
	if len(grades) == 0 {
		return 0, ErrNoGrades
	}
	sum := 0
	for _, grade := range grades {
		sum += grade
	}
	// Сумма переводится в float64 до деления: деление двух int
	// отбросило бы дробную часть, и среднее 4.4 стало бы 4.
	return math.Round(float64(sum)/float64(len(grades))*100) / 100, nil
}

Пять строк над func — комментарий документации. Он обращён к тому, кто будет вызывать CalculateAverage из другого пакета: что функция делает, как округляет результат и когда вместо среднего вернётся ошибка. Строка из одного // делит текст на абзацы. Запись [ErrNoGrades] в квадратных скобках — ссылка на другое имя пакета; синтаксис комментариев разобран в главе 4.8. Две строки внутри тела — обычный комментарий. Он объясняет выбор внутри функции и нужен тому, кто станет её править.

Разница проверяется командой go doc: она печатает документацию пакета или одного имени прямо в терминале. Выполните её в папке третьего архива:

Терминалgo doc ./internal/services CalculateAverage
$ go doc ./internal/services CalculateAverage
package services // import "example.com/otchet-kafe/internal/services"

func CalculateAverage(grades []int) (float64, error)
    CalculateAverage считает среднюю оценку по списку и округляет её до двух
    знаков после запятой.

    Для пустого списка возвращается ErrNoGrades: среднее по пустому списку не
    определено, поэтому нуль в этом случае не возвращается.

В ответе — подпись функции и текст комментария документации, заново разбитый на строки длиной около 80 знаков. Комментария из тела функции в ответе нет. Квадратные скобки вокруг ErrNoGrades тоже исчезли: в терминале ссылку показать нечем, а на сайте документации на этом месте будет ссылка.

Как соотносится с веткой Python

Докстринг Python сохраняется в самом объекте, и его можно прочитать из работающей программы через __doc__. Комментарий документации Go в собранную программу не попадает, как и любой комментарий. Его читают инструменты, которые разбирают исходный текст: go doc, gopls в редакторе, pkgsite. Поэтому для чтения документации нужны исходники пакета; в своём проекте они всегда лежат на диске.

Ассоциация: упаковка лекарства

В жизни

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

В коде

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

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

§4Что берут на себя имя и тип

Часть работы документации выполняют имя функции и типы в подписи. Имя CalculateAverage сообщает действие, подпись (grades []int) (float64, error) сообщает типы и то, что ошибка возможна. Повторять это словами не требуется.

Повтор подписи

// CalculateAverage принимает срез целых чисел grades и возвращает float64 и error.

→
То, чего в подписи нет

// CalculateAverage считает среднюю оценку и округляет её до двух знаков. Для пустого списка возвращается [ErrNoGrades].

В комментарий идёт то, что из подписи не следует: смысл значения, ограничения на входные данные, когда возвращается ошибка и какая, единицы измерения. Например, что суммы в проекте хранятся в копейках, из типа int не видно, и это место для комментария. Отдельный случай Go — ошибка в результатах: тип error говорит только, что ошибка возможна. Какая именно и в каком случае, сообщает комментарий.

На полях: тест и пример тоже документируют

Тест показывает поведение на конкретных данных: CalculateAverage([]int{5, 4, 5, 3, 5}) возвращает 4.4. Это точная запись ожидания, которую проверяет go test. В Go есть и промежуточный вид — функция-пример с именем ExampleFormatKopeks в файле _test.go. Она одновременно проверяется запуском и показывается в документации рядом с функцией. Примеры разобраны в главе 4.8.

§5Документация, собранная в сайт

Автоматическая документация — набор HTML-страниц, который программа собирает из исходного кода: проходит по пакетам, находит экспортируемые функции, типы, переменные и константы, забирает их подписи и комментарии документации и раскладывает по страницам с оглавлением и поиском. Так устроен сайт pkg.go.dev: на нём документация стандартной библиотеки Go и всех открытых модулей.

В Go для сборки ничего настраивать не нужно: формат комментариев один на весь язык, и инструменты читают его одинаково. Те же страницы, что на pkg.go.dev, программа pkgsite собирает и для своего проекта на своём компьютере. Запустите её в папке третьего архива:

Терминалсайт документации своего модуля
$ go run golang.org/x/pkgsite/cmd/pkgsite@latest

Команда go run с адресом программы и пометкой @latest скачивает последнюю версию pkgsite, собирает и запускает её; в go.mod проекта при этом ничего не добавляется. Первый запуск занимает больше времени: программа скачивается и собирается, следующие запуски берут её из кэша. Когда в терминале появится строка с адресом, откройте в браузере http://localhost:8080 и выберите пакет internal/services. Остановить программу — Ctrl + C в терминале.

Страница pkgsite для пакета services: описание пакета, оглавление Index со списком функций и переменных, разделы Variables и Functions
Страница пакета services, собранная pkgsite из третьего архива. В разделе Overview — комментарий пакета. Ниже Index — перечень всех экспортируемых имён; RevenueByWaiter стоит в нём под типом WaiterRevenue, как и в выводе go doc. Дальше идут разделы Variables с переменными ошибок ErrNoGrades и ErrNoOrders и Functions: у каждого имени подпись и текст его комментария. Слева — оглавление страницы. Имя ErrNoGrades в описании CalculateAverage стало ссылкой — так выглядит запись в квадратных скобках.

Путь от комментария до страницы

1 · Комментарий Строки // вплотную над объявлением. пишет разработчик
2 · Разбор Программа читает исходники и находит экспортируемые имена. настройка не нужна
3 · Показ go doc — в терминале, gopls — в подсказке, pkgsite — в браузере. одна команда
4 · pkg.go.dev Модуль из открытого репозитория появляется на общем сайте, когда его впервые запросят через прокси модулей Go. после публикации

Шаги 2–4 выполняют программы. От разработчика зависит шаг 1: на страницу попадает то, что написано в комментариях, и восполнить недостающее описание программе неоткуда.

§6Правило документирования в этом курсе

Каждое описание приходится поддерживать вместе с кодом, поэтому описывают не всё подряд. В Go граница проходит по видимости имени: описание обязательно там, где код вызывают из другого пакета, то есть у имён с заглавной буквы. Это же правило проверяет revive.

Комментарий документации обязателен

Каждый пакетКомментарий над строкой package в одном из файлов пакета: за что этот пакет отвечает. У пакета main — что делает программа и как её запустить.
Экспортируемая функция и методВсё, что начинается с заглавной буквы и вызывается из другого пакета.
Экспортируемый типЧто представляет значение этого типа; у полей структуры — короткий комментарий в конце строки.
Экспортируемая переменная ошибкиErrNoGrades и подобные: в каком случае её возвращают. По этому описанию вызывающий код решает, какую ошибку проверять.

Функции с именем со строчной буквы, например squashSpaces, вызываются только внутри своего пакета. Для них достаточно одной строки, а можно обойтись и без комментария. Проверка, что правило соблюдено, настраивается в главе 4.10.

§7Частые вопросы

Обычно думаютХороший код понятен без документации, поэтому комментарии нужны только плохому коду.
На самом делеПонятный код отвечает на вопрос «как это работает». Комментарий документации отвечает на вопрос «что эта функция обещает вызывающему»: границы входных данных, единицы измерения, какие ошибки она возвращает. Из тела функции это выясняется чтением, из комментария — сразу.
Обычно думаютЛюбой комментарий над функцией попадёт в документацию.
На самом делеТолько тот, что стоит вплотную, без пустой строки. Комментарий, отделённый пустой строкой, go doc и редактор не показывают.
Обычно думаютЕсли есть README, комментарии документации не нужны.
На самом делеREADME отвечает на вопросы о проекте целиком: назначение, установка, запуск. Описание каждой функции большого проекта в него не поместится, и читать его в момент вызова неудобно.
Обычно думаютДокументацию пишут в конце, когда код готов.
На самом делеОписание, написанное через месяц после кода, приходится восстанавливать чтением собственного кода. Комментарий пишется вместе с функцией и правится вместе с ней: тогда он совпадает с поведением.

§8Проверьте себя

Чем комментарий документации отличается от обычного комментария?

Только местом. Комментарий документации стоит вплотную, без пустой строки, над объявлением верхнего уровня: package, func, type, var, const. Его показывают go doc, подсказка редактора и pkgsite. Комментарий внутри тела или отделённый пустой строкой эти инструменты пропускают.

Функция возвращает (float64, error). Что остаётся написать в комментарии?

То, чего в подписи нет: что функция делает, смысл значения и единицы измерения, ограничения на входные данные и в каком случае возвращается ошибка — желательно с именем переменной ошибки в квадратных скобках, например [ErrNoGrades]. Перечисление типов словами дублирует подпись.

Какие виды документации обновляются вместе с кодом, а какие отдельно?

Обычный комментарий, комментарий документации и тип в подписи лежат в том же файле и правятся вместе с функцией. README лежит отдельно и обновляется отдельным действием. Сайт документации не правится вручную: меняют комментарии в исходниках, и pkgsite собирает страницы заново.

Попадает ли комментарий документации в собранную программу, как докстринг Python в __doc__?

Нет. Компилятор отбрасывает все комментарии. Документацию читают инструменты, которые разбирают исходный текст: go doc, gopls, pkgsite.

У функции имя начинается со строчной буквы. Обязателен ли для неё комментарий по правилу курса?

Нет. Строчная буква означает, что функция не экспортируется и вызывается только внутри своего пакета. Для неё достаточно одной строки, а можно обойтись и без комментария. Обязательны комментарии у пакетов и у всех экспортируемых имён.

§9Шпаргалка по главе

Комментарий // внутри тела функции читает тот, кто правит
Комментарий документации // вплотную над func читает тот, кто вызывает go doc, подсказка, pkgsite
Тип в подписи func F(x int) (string, error) только типы
README о проекте целиком назначение, запуск, состав
Сайт документации go run golang.org/x/pkgsite/cmd/pkgsite@latest http://localhost:8080
Обязательно описывать каждый пакет имена с заглавной буквы переменные ошибок

Итог главы

Документация кода — текст о назначении программы, который хранится вместе с исходниками. В проекте на Go её пять видов: комментарий внутри тела, комментарий документации над объявлением, тип в подписи, README о проекте целиком и собранный программой сайт. Обычный комментарий и комментарий документации записываются одинаково, через //; документацией строку делает место — вплотную над объявлением верхнего уровня. Её показывают go doc, подсказка редактора и pkgsite. Имя и подпись сообщают действие и типы, поэтому в комментарий идут ограничения, единицы измерения и случаи, когда возвращается ошибка. В курсе комментарии обязательны у пакетов и у экспортируемых имён. В следующей главе разобрано, как комментарий документации устроен: где он стоит, как его прочитать и какие правила задаёт Go.

Откуда взяты факты
  1. Определение комментария документации и его место в файле — Go Doc Comments.
  2. Команда go doc — документация команды go, Show documentation for package or symbol.
  3. Программа pkgsite и сайт pkg.go.dev — pkgsite, About pkg.go.dev.
  4. Выводы go doc получены на третьем архиве с Go 1.27; страница pkgsite снята с того же архива.
Глава 4.6 · Виды документации кода · МДК.01.01 Автор: Макаров Максим Николаевич