Именование для Go

Именование для Go #

В языке Go есть несколько правил хорошего стиля для идентификаторов в коде:

  1. Имя пакета влияет на имя символа
  2. Интерфейсы не имеют префикса в имени
  3. Интерфейсы часто имеют суффикс -er/-or
  4. Краткость — это норма
  5. Аббревиатуры пишутся в верхнем регистре
  6. Функции-конструкторы имеют префикс New
  7. Известные ошибки имеют префикс Err
  8. Не используйте префикс Get для геттеров

Разберём эти правила подробно на примерах.

Имя пакета влияет на имя символа #

При импорте имя пакета станет частью полного имени, и это стоит учитывать в именовании символов, экспортируемых из пакета.

Примеры полных имён после импорта в другом пакете:

  • auth.Token — токен аутентификации
  • courses.Course — курс
  • courses.Module — модуль курса

Такой стиль именования часто обыгрывается в стандартной библиотеке Go, например: slices.Sort

Интерфейсы не имеют префикса в имени #

В языке C# интерфейсам принято добавлять префикс I, в языке PHP — суффикс Interface. В Go так не принято.

Это правило вызывает вопрос: как назвать реализацию, если имя уже занято интерфейсом? Есть много способов избежать конфликта имён:

  1. можно расположить интерфейс и реализацию в одном пакете, но экспортировать только интерфейс:
    • интерфейс Module в пакете auth
    • реализация module в пакете auth
  2. можно расположить интерфейс и реализацию в разных пакетах, например:
    • интерфейс domain.UserRepository
    • реализация infra.UserRepository
  3. можно добавить префикс/суффикс к реализации, например:
    • интерфейс AuthService
    • декоратор LoggingAuthService
  4. можно добавить детали реализации в имя реализации интерфейса, например:
    • интерфейс RateLimiter
    • реализация RedisRateLimiter
  5. можно назвать интерфейс иначе, например:
    • интерфейс Bookable
    • реализация Room

Связанное правило: в Go принято возвращать из функций/методов не интерфейс, а реализацию. Параметром функции/метода, напротив, лучше принимать интерфейс.

Интерфейсы часто имеют суффикс -er/-or #

Простые интерфейсы обычно определяют одно простое поведение и часто объявляют лишь один метод.

Такие интерфейсы часто имеют суффикс -er или -or:

type Reader interface {
    Read(p []byte) (n int, err error)
}

Краткость — это норма #

Длинные имена не приветствуются, а общепринятые сокращения применяются постоянно.

Примеры:

  • пакет auth вместо authentication
  • функция Migrate() вместо RunDatabaseMigrations()

Для локальных переменных и параметров часто применяются однобуквенные имена:

  • c вместо course
  • i вместо index

Здесь важен баланс: если у функции/метода много параметров или большое тело, то лучше дать локальным переменным и параметрам более длинные, понятные имена.

Некоторые переменные имеют общепринятые имена:

  • Переменные типа error называются просто err — либо чуть длиннее, если err уже занято: closeErr, rollbackErr
  • Переменные типа context.Context называются ctx

Аббревиатуры пишутся в верхнем регистре #

Аббревиатуры пишутся в верхнем регистре, например:

  • функция ParseURL
  • поле LLMAPIKey

Есть случаи, когда аббревиатуры пишутся в нижнем регистре:

  • имена пакетов: http
  • начало имени символа, если он не экспортируется: httpServer

Функции-конструкторы имеют префикс New #

Для создания объектов обычно заводятся функции-конструкторы, к именам которых лучше добавить префикс “New” / “new”.

Примеры:

Имя при вызовеОбъявление функции
courses.New()func New() *courses.Course
courses.NewModule()func NewModule() *courses.Module
auth.NewLearner()func NewLearner() *auth.User

Известные ошибки имеют префикс Err #

Для распознавания известных ошибок принято использовать условно-неизменные переменные с префиксом “Err”:

var ErrConflict = errors.New("entity has been changed in another transaction")

Эту переменную нельзя заменить константой, потому что в Go константа может иметь только базовый тип.

Не используйте префикс Get для геттеров #

Для геттеров просто пишите название получаемого свойства без глагола, например: user.Email().


Сайт atdd.ru — блог разработчика.