Question
I am writing a basic Go program that calls a function defined in a different file but within the same package. However, I get an error saying that NewEmployee is undefined.
Here is the code:
// main.go
package main
func main() {
emp := NewEmployee()
_ = emp
}
// employee.go
package main
type Employee struct {
name string
age int
}
func NewEmployee() *Employee {
p := &Employee{}
return p
}
func PrintEmployee(p *Employee) string {
return "Hello world!"
}
Why would a function declared in another file of the same package be reported as undefined, and how should this be set up correctly in Go?
Short Answer
By the end of this page, you will understand how Go treats multiple files in the same package, why a function can still appear as undefined, how to compile and run Go code correctly, and how exported and unexported names affect visibility.
Concept
In Go, files that belong to the same package are compiled together. That means a function defined in employee.go should be available in main.go as long as both files are in the same folder and are built together.
In your example, both files use:
package main
So NewEmployee() is visible to main.go without any import.
If Go says undefined: NewEmployee, the problem is usually not the function definition itself. The most common cause is that only one file is being run or built.
For example, if you run:
go run main.go
Go will compile only main.go, not employee.go. Since employee.go is excluded, NewEmployee() does not exist from the compiler's point of view.
Instead, you should run the whole package:
go run .
or:
go build
Mental Model
Think of a Go package like a folder of recipe cards that are all used to make one meal.
- Each
.gofile is one recipe card. - The
packageline says which meal that card belongs to. - When Go builds the package, it gathers all recipe cards in the same folder and package.
If you only hand Go one card, like main.go, it cannot see the instructions written on employee.go.
So the issue is usually not "the function is in another file". The issue is "that file was not included in the build."
Syntax and Examples
In Go, functions in the same package can be used directly across files.
Example structure
// main.go
package main
import "fmt"
func main() {
emp := NewEmployee()
fmt.Println(emp)
fmt.Println(PrintEmployee(emp))
}
// employee.go
package main
type Employee struct {
name string
age int
}
func NewEmployee() *Employee {
return &Employee{name: "Alice", age: 30}
}
func PrintEmployee(p *Employee) string {
return "Hello world!"
}
How to run it
Run the package, not a single file:
go run .
Why this works
- Both files are in the same directory.
- Both files declare
package main.
Step by Step Execution
Consider this code:
// main.go
package main
import "fmt"
func main() {
emp := NewEmployee()
fmt.Println(PrintEmployee(emp))
}
// employee.go
package main
type Employee struct {
name string
age int
}
func NewEmployee() *Employee {
return &Employee{name: "Sam", age: 25}
}
func PrintEmployee(p *Employee) string {
return p.name
}
Step-by-step
- Go loads the current package.
- It sees both
main.goandemployee.gobecause both are in the same folder and package. main()starts running.NewEmployee()is called.NewEmployee()creates an value and returns a pointer to it.
Real World Use Cases
This concept is used constantly in real Go projects.
Splitting code by responsibility
A package may be divided into multiple files such as:
main.gofor program startupemployee.gofor employee-related types and functionsdb.gofor database accessconfig.gofor configuration loading
All of these can belong to the same package if they are closely related.
Keeping code readable
As a program grows, putting everything in one file becomes hard to manage. Multiple files let you:
- group related types and functions
- reduce clutter
- make code easier to navigate
Building command-line tools
In a CLI app, you might have:
main.goto parse flagscommands.goto define command handlershelpers.gofor utility functions
They can all work together in the same package.
Web applications
A small web server might use:
main.gofor startuproutes.gofor route setup
Real Codebase Usage
In real projects, developers use package-level organization intentionally.
Common patterns
Grouping related code in one package
A package often contains several files:
user.gouser_service.gouser_validation.go
All can share unexported helpers if they are in the same package.
Constructors
Functions like NewEmployee() are common constructor-style functions:
func NewEmployee(name string, age int) *Employee {
return &Employee{name: name, age: age}
}
This helps centralize setup logic.
Validation before creation
func NewEmployee(name string, age int) (*Employee, error) {
if name == "" {
return nil, errors.New()
}
age < {
, errors.New()
}
&Employee{name: name, age: age},
}
Common Mistakes
Here are common mistakes beginners make with this topic.
1. Running only one file
Broken
go run main.go
If NewEmployee() is in another file, this can cause:
undefined: NewEmployee
Fix
go run .
or:
go build
2. Using different package names in the same folder
Broken
// main.go
package main
// employee.go
package employee
Files in one folder generally need to belong to the same package for this kind of direct access.
Fix
Use the same package name if they are meant to compile together:
package main
3. Forgetting to export names across packages
Comparisons
| Situation | Can you call the function directly? | What is required? |
|---|---|---|
| Same package, same folder, built together | Yes | Same package name |
| Same package, but only one file is run | No | Run/build the whole package |
| Different packages | No | Import the package and use exported names |
| Same folder, different package names | No | Reorganize package structure |
Same package vs different package
| Feature | Same package | Different package |
|---|---|---|
| Direct access to functions | Yes | No |
| Need |
Cheat Sheet
// File 1
package main
func Hello() string {
return "hi"
}
// File 2
package main
func main() {
println(Hello())
}
Rules
- Files in the same package can use each other's functions directly.
- Files must usually be in the same directory and use the same
packagename. - Run the whole package with:
go run .go build
- If you run only one file, other files are not included.
- Uppercase names are exported.
- Lowercase names are package-private.
- Across different packages, you must:
importthe package- use exported names only
Common fix for undefined
If your code is split across files in one package:
FAQ
Why does Go say a function is undefined when it is in another file?
Usually because you ran only one file, such as go run main.go, instead of building the whole package.
How do I run all Go files in the same package?
Use:
go run .
Do files in the same Go package need imports between them?
No. Functions, types, and variables in the same package are available directly.
Does the function name need to start with an uppercase letter?
Only if you want to use it from another package. Inside the same package, lowercase names also work.
Can two files in the same folder have different package names?
Not for normal package usage like this. If they do, they are treated as different packages and cannot access each other directly.
Why does my PrintEmployee function fail to compile?
Because it returns a string but the function signature did not declare a return type.
What is the difference between go build and go run .?
go build compiles the package. go run . compiles and runs it immediately.
Can I split a Go package into many files?
Yes. That is a common and recommended way to organize related code.
Mini Project
Description
Create a small multi-file Go program that manages employees. This project demonstrates how functions, structs, and constructor-style functions work across multiple files in the same package.
Goal
Build and run a two-file Go program where main.go creates an employee using a function from employee.go and prints employee information.
Requirements
Requirement 1 Requirement 2 Requirement 3
Keep learning
Related questions
Blank Identifier Imports in Go: What `_` Means in an Import Statement
Learn what `_` means in a Go import, why blank identifier imports run package init code, and when to use them safely.
Check if a Value Exists in a Slice in Go
Learn how to check whether a value exists in a slice in Go, and why Go has no Python-style `in` operator for arrays or slices.
Concatenating Slices in Go with append
Learn how to concatenate two slices in Go using append and the ... operator, with examples, pitfalls, and practical usage.