\ Когда я начал изучать Go, одним из первых вопросов был:
"Как мне на самом деле структурировать свой код?"
В таких языках, как C, принято помещать всё в один файл или, возможно, разделять файлы заголовков и реализации. Но в Go структура проекта имеет большое значение: она влияет на то, насколько легко можно масштабировать, тестировать и делиться своим кодом. В этой статье я расскажу, почему структура важна, как получить доступ к функциям из разных файлов и какие лучшие практики я изучаю по мере продвижения вперед.
Программа на Go может полностью находиться в одном файле:
package main import "fmt" func main() { fmt.Println("2 + 2 =", 2+2) }
Это хорошо работает для "hello world" или быстрых экспериментов.
Но как только вы добавляете больше функциональности (вычитание, умножение, деление...), файл становится беспорядочным и трудно масштабируемым.
Вот где на помощь приходят пакеты и папки Go.
В Go каждый файл принадлежит пакету.
По соглашению:
Вот как я разделил проект калькулятора:
calculator/ │ ├── main.go └── calculator/ └── 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 }
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.
\
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 }
\
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
Распространенные ошибки и исправления
❌ 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 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, эта структура становится необходимой.
Я продолжу делиться тем, что узнаю, исследуя Go для MLOps и бэкенд-разработки. Далее: обработка ошибок и тестирование в Go.
\ 👉 Посмотрите мой репозиторий здесь: https://github.com/turman17/GoLang-progress
И следите за следующей статьей!


