Именование для Go #
В языке Go есть несколько правил хорошего стиля для идентификаторов в коде:
- Имя пакета влияет на имя символа
- Интерфейсы не имеют префикса в имени
- Интерфейсы часто имеют суффикс -er/-or
- Краткость — это норма
- Аббревиатуры пишутся в верхнем регистре
- Функции-конструкторы имеют префикс New
- Известные ошибки имеют префикс Err
- Не используйте префикс Get для геттеров
Разберём эти правила подробно на примерах.
Имя пакета влияет на имя символа #
При импорте имя пакета станет частью полного имени, и это стоит учитывать в именовании символов, экспортируемых из пакета.
Примеры полных имён после импорта в другом пакете:
auth.Token— токен аутентификацииcourses.Course— курсcourses.Module— модуль курса
Такой стиль именования часто обыгрывается в стандартной библиотеке Go, например: slices.Sort
Интерфейсы не имеют префикса в имени #
В языке C# интерфейсам принято добавлять префикс I, в языке PHP — суффикс Interface. В Go так не принято.
Это правило вызывает вопрос: как назвать реализацию, если имя уже занято интерфейсом? Есть много способов избежать конфликта имён:
- можно расположить интерфейс и реализацию в одном пакете, но экспортировать только интерфейс:
- интерфейс
Moduleв пакетеauth - реализация
moduleв пакетеauth
- интерфейс
- можно расположить интерфейс и реализацию в разных пакетах, например:
- интерфейс
domain.UserRepository - реализация
infra.UserRepository
- интерфейс
- можно добавить префикс/суффикс к реализации, например:
- интерфейс
AuthService - декоратор
LoggingAuthService
- интерфейс
- можно добавить детали реализации в имя реализации интерфейса, например:
- интерфейс
RateLimiter - реализация
RedisRateLimiter
- интерфейс
- можно назвать интерфейс иначе, например:
- интерфейс
Bookable - реализация
Room
- интерфейс
Связанное правило: в Go принято возвращать из функций/методов не интерфейс, а реализацию. Параметром функции/метода, напротив, лучше принимать интерфейс.
Интерфейсы часто имеют суффикс -er/-or #
Простые интерфейсы обычно определяют одно простое поведение и часто объявляют лишь один метод.
Такие интерфейсы часто имеют суффикс -er или -or:
type Reader interface {
Read(p []byte) (n int, err error)
}Краткость — это норма #
Длинные имена не приветствуются, а общепринятые сокращения применяются постоянно.
Примеры:
- пакет
authвместоauthentication - функция
Migrate()вместоRunDatabaseMigrations()
Для локальных переменных и параметров часто применяются однобуквенные имена:
cвместоcourseiвместо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().