Узнайте, как правильно структурировать код Go: от проектов с одним файлом до пакетов, внутренних модулей и правильного импорта, объясненных на примере калькулятора.Узнайте, как правильно структурировать код Go: от проектов с одним файлом до пакетов, внутренних модулей и правильного импорта, объясненных на примере калькулятора.

Как организовать свои Go проекты как профессионал

2025/10/06 11:36
4м. чтение
Для обратной связи или замечаний по поводу данного контента, свяжитесь с нами по адресу crypto.news@mexc.com

\ Когда я начал изучать Go, одним из первых вопросов был:

"Как мне на самом деле структурировать свой код?"

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


Самая простая программа на Go

Программа на Go может полностью находиться в одном файле:

package main  import "fmt"  func main() {   fmt.Println("2 + 2 =", 2+2) } 

Это хорошо работает для "hello world" или быстрых экспериментов.

Но как только вы добавляете больше функциональности (вычитание, умножение, деление...), файл становится беспорядочным и трудно масштабируемым.

Вот где на помощь приходят пакеты и папки Go.


Введение в пакеты

В Go каждый файл принадлежит пакету.

По соглашению:

  • main → исполняемая программа
  • другие (например, calculator, utils и т.д.) → многоразовая логика

Вот как я разделил проект калькулятора:

calculator/ │ ├── main.go └── calculator/     └── operations.go 

\

  • main.go → обрабатывает ввод/вывод
  • operations.go → определяет функции, такие как Add, Subtract и т.д.

Пример: operations.go

package calculator  func Add(a, b int) int {   return a + b }  func Subtract(a, b int) int {   return a - b }  func Multiply(a, b int) int {   return a * b }  func Divide(a, b int) (int, error) {   if b == 0 {     return 0, fmt.Errorf("cannot divide by zero")   }   return a / b, nil } 

Пример: main.go

package main  import (   "fmt"   "GoLang-progress/calculator" )  func main() {   fmt.Println("2 + 3 =", calculator.Add(2, 3))   fmt.Println("10 - 4 =", calculator.Subtract(10, 4))   fmt.Println("6 * 7 =", calculator.Multiply(6, 7))    result, err := calculator.Divide(8, 0)   if err != nil {     fmt.Println("Error:", err)   } else {     fmt.Println("8 / 0 =", result)   } } 

Обратите внимание, как main.go теперь чистый: он не беспокоится о самой математике, только о том, как её использовать.


Доступ к функциям из разных файлов

Распространенный вопрос новичков:

"Как мне вызвать функцию из другого файла или папки?"

В моем репозитории я структурировал это так:

calculator/ │ ├── main.go └── internal/     └── calc/         └── operations.go 

Здесь математические функции находятся в internal/calc.

operations.go (внутри internal/calc)

\

package calc  import "fmt"  func Add(a, b int) int {   return a + b }  func Divide(a, b int) (int, error) {   if b == 0 {     return 0, fmt.Errorf("cannot divide by zero")   }   return a / b, nil } 

main.go (импортирует internal/calc)

\

package main  import (   "fmt"   "github.com/turman17/GoLang-progress/calculator/internal/calc" )  func main() {   fmt.Println("2 + 3 =", calc.Add(2, 3))    result, err := calc.Divide(10, 0)   if err != nil {     fmt.Println("Error:", err)   } else {     fmt.Println("10 / 2 =", result)   } } 

Почему требуется этот путь импорта

Ваш импорт должен соответствовать вашему пути модуля из go.mod плюс путь к папке.

В вашем репозитории go.mod содержит:

module github.com/turman17/GoLang-progress 

Код калькулятора, который вы хотите использовать, находится в папке:

calculator/internal/calc 

Таким образом, полный путь импорта:

github.com/turman17/GoLang-progress/calculator/internal/calc 

Несколько важных примечаний

  • Имя папки ≠ имя пакета → Папка - internal/calc, но пакет внутри объявлен как package calc.
  • Импорты используют путь модуля → Всегда начинайте с github.com/..., если это указано в вашем go.mod.
  • Internal особенный → Пакеты под /internal могут быть импортированы только кодом внутри того же модуля.

Распространенные ошибки и исправления

❌ import "GoLang-progress/calculator/internal/calc"

→ Отсутствует организация/имя пользователя GitHub. Необходимо использовать полный путь.

❌ import "github.com/turman17/GoLang-progress/internal/calc"

→ Отсутствует директория calculator в пути.

❌ go: module not found errors

→ Убедитесь, что go.mod содержит module github.com/turman17/GoLang-progress и выполните go mod tidy.


Быстрый чек-лист

  • go.mod имеет правильную строку модуля
  • Директория - calculator/internal/calc с пакетом calc внутри
  • main.go импортирует github.com/turman17/GoLang-progress/calculator/internal/calc
  • Сборка из корня модуля:

\

go run ./calculator 

или

go build ./calculator 

Масштабирование структуры

По мере роста проектов вы часто будете видеть такой шаблон:

project-name/ │ ├── cmd/        → executables (main entrypoints) ├── internal/   → private code (not for external use) ├── pkg/        → reusable packages ├── api/        → API definitions (gRPC, OpenAPI, etc.) └── go.mod 

Для начинающих это может быть излишним. Но когда вы переходите к веб-приложениям, сервисам или инструментам MLOps, эта структура становится необходимой.


Лучшие практики, которые я изучаю

  • Делайте пакеты маленькими и целенаправленными
  • Используйте осмысленные имена (calc, parser, storage)
  • Не переусложняйте — начинайте просто, рефакторите позже
  • Избегайте циклических зависимостей (Go обеспечивает это)

Уроки из проекта калькулятора

  • Отделение логики (operations.go) от точки входа (main.go) упрощает тестирование.
  • Обработка ошибок (например, деление на ноль) должна быть явной.
  • Пути импорта действительно важны — особенно при использовании internal.

Я продолжу делиться тем, что узнаю, исследуя Go для MLOps и бэкенд-разработки. Далее: обработка ошибок и тестирование в Go.

\ 👉 Посмотрите мой репозиторий здесь: https://github.com/turman17/GoLang-progress

И следите за следующей статьей!

Возможности рынка
Логотип Wink
Wink Курс (LIKE)
--
----
USD
График цены Wink (LIKE) в реальном времени

Комбо Кубка мира: Цель на 200x

Комбо Кубка мира: Цель на 200xКомбо Кубка мира: Цель на 200x

До 20 комбо в матчах Кубка мира за 1 ордер

Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу crypto.news@mexc.com для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.

Вам также может быть интересно

Акции (Beta) уже доступны

Акции (Beta) уже доступныАкции (Beta) уже доступны

Торгуйте акциями США через лицензированного брокера