Avatar ·

Соглашения по именованию файлов в Go: snake_case или что-то ещё?

Привет! Я начал изучать Go недавно, перешёл с Python, и меня немного смущает вопрос именования файлов. В Python я привык к snake_case для модулей и файлов, но в Go, судя по стандартной библиотеке, используется snake_case с подчёркиваниями, и я вижу, что некоторые файлы называются, например, `http.go`, `transport.go`, `server.go`. Но я также встречал в open-source проектах файлы типа `myHandler.go`, `MyService.go` или даже `user_repository.go`. Как правильно? Вот пример моего проекта, где я пытаюсь организовать код: ```go // Мой проект: простой REST API для заметок // Файл: main.go package main import "fmt" func main() { fmt.Println("Hello, Notes API!") } // Файл: handlers.go package main // Обработчик для создания заметки func CreateNoteHandler() { // ... } // Файл: models.go package main type Note struct { ID int Text string } ``` Я не уверен, стоит ли называть файлы с большой буквы (как `Handlers.go`) или использовать подчёркивания (`handlers.go` или `handlers_api.go`). Есть ли строгие правила? И как быть, если у меня много файлов в одном пакете? Заранее спасибо за помощь! <<>>

Основные правила именования файлов в Go

В Go нет жёстких синтаксических ограничений на имена файлов (кроме того, что они должны быть валидными для ОС), но есть устоявшиеся конвенции, которым следуют почти все Go-разработчики. Давайте разберём их по порядку.

1. Всегда используйте snake_case (строчные буквы с подчёркиваниями)

Это главное правило. Имена файлов должны быть в нижнем регистре, слова разделяются подчёркиванием _. Никакого CamelCase или PascalCase для файлов. Почему? Потому что на некоторых файловых системах (например, macOS по умолчанию нечувствительна к регистру, а Linux — чувствительна). Если вы назовёте файл MyHandler.go на macOS, он может работать, но на Linux вы получите ошибку, если где-то в импорте или сборке будет ссылка на myhandler.go.

Пример правильного именования:

// Плохо
MyHandler.go
UserRepository.go

// Хорошо
my_handler.go
user_repository.go

2. Имя файла должно отражать его содержимое

В Go принято, чтобы один файл содержал логически связанный код. Например:

  • handlers.go — HTTP-обработчики
  • models.go — структуры данных (модели)
  • routes.go — маршруты
  • middleware.go — промежуточное ПО
  • errors.go — определения ошибок
  • testing.go — тесты (хотя обычно тесты лежат в _test.go)

3. Специальные суффиксы: _test, _os, _arch

Go использует соглашения для условной компиляции и тестирования:

  • Тесты: файлы должны заканчиваться на _test.go. Например, handlers_test.go.
  • Платформозависимый код: используйте суффиксы _linux.go, _windows.go, _darwin.go и т.д. Например, file_unix.go, file_windows.go.
  • Архитектурозависимый код: _amd64.go, _arm.go и т.д.

4. Имя файла не должно совпадать с именем пакета

Хотя технически это возможно, это может вызвать путаницу. Например, если ваш пакет называется handler, не называйте файл handler.go — лучше handlers.go или handler_impl.go.

5. Пример правильной структуры вашего проекта

Вот как можно организовать ваш проект с заметками:

// main.go
package main

func main() {
    // ...
}

// handlers.go
package main

func CreateNoteHandler() { ... }
func GetNoteHandler()    { ... }

// models.go
package main

type Note struct {
    ID   int
    Text string
}

// routes.go
package main

func SetupRoutes() { ... }

// database.go
package main

func InitDB() { ... }
func SaveNote(n Note) error { ... }

6. Что насчёт одного файла на тип?

В некоторых языках (Java, C#) принято иметь один файл на класс. В Go это не обязательно. Обычно один файл содержит несколько связанных типов и функций. Разделяйте файлы по логическим модулям, а не по каждому типу. Например:

  • types.go — все основные типы и константы
  • validation.go — функции валидации
  • serialization.go — JSON/XML сериализация

7. Исключения из правил

Иногда в стандартной библиотеке Go встречаются файлы с одним словом без подчёркиваний: http.go, json.go, fmt.go. Это нормально, если имя короткое и однозначное. Но если имя состоит из нескольких слов, используйте подчёркивания: http_transport.go, json_encoder.go.

Итог: для вашего проекта используйте handlers.go, models.go, routes.go — это будет соответствовать конвенциям Go и не вызовет проблем на разных платформах.

<<>>

Альтернативный подход: группировка по функциональности

В дополнение к основным правилам, в крупных проектах часто используется стратегия «один файл — одна ответственность», но не в смысле «один тип», а в смысле «одна функциональная область». Например, если у вас есть пакет api, вы можете разбить его так:

api/
├── create.go       // логика создания ресурса
├── get.go          // логика получения
├── update.go       // обновление
├── delete.go       // удаление
├── middleware.go   // middleware
└── errors.go       // ошибки

Этот подход особенно удобен, когда обработчики становятся большими. Каждый файл содержит ровно одну функцию-обработчик и связанные с ней вспомогательные функции. Имена файлов при этом отражают HTTP-метод или операцию, а не просто «handlers».

Важно: даже при таком подходе сохраняйте snake_case. Не называйте файл CreateNote.go — правильно create_note.go.

Когда использовать CamelCase?

Единственный случай, когда в имени файла может быть заглавная буква — это если файл экспортирует только один тип и вы хотите подчеркнуть, что это основной тип пакета. Но это редкое исключение, и даже в стандартной библиотеке так не делают. Лучше всегда придерживаться snake_case.