Go ругается "undefined" на функцию из другого файла? Разбираем

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

«Undefined» функция в Go: как подружить файлы и не сойти с ума

Представьте: вы пишете на Go программу, разбиваете код на логические файлы (например, main.go и helper.go), запускаете go run main.go — и компилятор выдаёт ледяное: «undefined: MyFunction». Знакомо? Этот вопрос — один из самых популярных на Stack Overflow (тысячи просмотров!), и сегодня мы разберём его раз и навсегда.

Почему Go, который славится своей простотой, вдруг не видит функцию из соседнего файла? Дело не в магии, а в строгих правилах организации кода. Давайте пройдёмся по всем сценариям — от классической ошибки новичка до правильной работы с модулями.

Сценарий 1: Классика — забыли указать все файлы при запуске

Самый частый случай. Вы пишете:

// main.go
package main

func main() {
    printHello() // Ошибка: undefined: printHello
}
// helper.go
package main

import "fmt"

func printHello() {
    fmt.Println("Hello!")
}

И запускаете только go run main.go. Go не видит helper.go, потому что вы явно не указали его. Правильное решение:

go run main.go helper.go
// или проще:
go run .

Почему так? Go не сканирует директорию автоматически — вы должны перечислить все файлы пакета. Команда go run . запускает всю текущую папку как единый пакет.

Сценарий 2: Разные пакеты — невидимость по умолчанию

Другая популярная ловушка — попытка вызвать функцию из другого пакета без импорта и экспорта.

// main.go
package main

func main() {
    helper.DoSomething() // Ошибка: undefined: helper
}
// helper/helper.go
package helper

func DoSomething() {
    // ...
}

Здесь две проблемы:

  • Файлы находятся в разных пакетах (main и helper).
  • Функция DoSomething не экспортирована (начинается с маленькой буквы).

Исправленный вариант:

// main.go
package main

import "yourmodule/helper"

func main() {
    helper.DoSomething() // Работает!
}
// helper/helper.go
package helper

func DoSomething() { // Большая буква!
    // ...
}

Запомните: В Go экспортируются только сущности с заглавной буквы. Маленькая буква — приватно для пакета.

Сценарий 3: Проблемы с модулями и GOPATH

Если вы используете старый стиль (GOPATH) или неправильно инициализировали модуль, Go может не найти ваши файлы даже в одной папке.

Проверьте:

  1. Есть ли файл go.mod в корне проекта? Если нет — создайте: go mod init имя_модуля.
  2. Не храните ли вы проект внутри $GOPATH/src без модуля? Это legacy-режим, который может путать.
  3. Убедитесь, что все файлы в папке имеют одинаковый package (кроме тестовых файлов с суффиксом _test).

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

myproject/
├── go.mod          # module myproject
├── main.go         # package main
└── helper.go       # package main

Сценарий 4: Имена файлов с подчёркиваниями и тестовые файлы

Go игнорирует файлы, начинающиеся с _ или . (например, _hidden.go). А файлы с суффиксом _test.go собираются только при запуске тестов (go test). Если вы случайно назвали рабочий файл как helper_test.go — его функции не будут видны в основном коде.

Сценарий 5: Циклические зависимости

Иногда ошибка «undefined» может быть следствием циклического импорта. Например, пакет A импортирует B, а B импортирует A. Go запрещает такие циклы и может выдавать странные ошибки. Решение: вынести общие типы или функции в третий пакет.

Как избежать ошибки «undefined function»: чек-лист

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

  • Все ли файлы указаны при запуске? Используйте go run . или go build ..
  • Один ли пакет? Все файлы в одной папке должны иметь одинаковый package (обычно package main).
  • Экспортирована ли функция? Имя должно начинаться с заглавной буквы, если вы вызываете её из другого пакета.
  • Импортирован ли пакет? Если функция в другом пакете — добавьте import и используйте синтаксис пакет.Функция.
  • Инициализирован ли модуль? Проверьте наличие go.mod. Если нет — выполните go mod init.
  • Нет ли лишних символов в имени файла? Избегайте _ и . в начале имени файла (кроме тестов).

Продвинутый совет: init() и порядок инициализации

Иногда новички путают ошибку «undefined» с тем, что функция просто не успела выполниться. В Go есть функции init(), которые запускаются автоматически при загрузке пакета. Они не могут быть вызваны напрямую из другого файла — только срабатывают сами. Если вы объявили init() в одном файле, а пытаетесь вызвать её из другого — получите «undefined». Правильно: init() нельзя вызывать вручную, это не обычная функция.

// config.go
package main

func init() {
    // Эта функция выполнится сама при старте программы
    SetupLogger()
}

// main.go
package main

func main() {
    // init() уже отработал, вызывать его не нужно
}

Реальный пример из жизни: разбиваем проект на файлы

Допустим, вы пишете небольшой HTTP-сервер. Вот как правильно организовать код:

// main.go
package main

func main() {
    startServer() // функция из server.go
}
// server.go
package main

import (
    "fmt"
    "net/http"
)

func startServer() {
    http.HandleFunc("/", handler)
    fmt.Println                

Блоги

Рекомендаций по книгам