Question
How can I call the demo function defined in test2.go from the main function in test1.go?
// test1.go
package main
func main() {
demo()
}
// test2.go
package main
import "fmt"
func demo() {
fmt.Println("HI")
}
What changes are required, and how should the program be run?
Short Answer
You will learn how Go compiles files in the same directory and package together, why a program can have only one main function, and how to run all source files so one file can call functions declared in another.
Concept
Go organizes code primarily with packages, not individual files. Files in the same directory that declare the same package are compiled together.
For example, if both files contain:
package main
then test1.go can call a function declared in test2.go directly:
demo()
No import is needed between those two files. The fmt import belongs only in the file that uses fmt.
A runnable Go application uses package main and must contain exactly one function named main. The main function is the program's entry point. Other files in the same package can contain helper functions, but they must not define another main function.
This matters because splitting code into files keeps programs organized: one file may handle startup, another may format output, and another may contain application logic.
Mental Model
Think of a Go package as a shared workspace.
Each .go file in the same folder and package is like a page placed on the same desk. Everyone working at that desk can see the functions written on every page. Therefore, test1.go can use demo from test2.go without an import.
The main function is the building's front door. A program can have one front door, so there can be only one main function in package main.
Syntax and Examples
Put both files in the same folder and give them the same package declaration.
// main.go
package main
func main() {
demo()
}
// demo.go
package main
import "fmt"
func demo() {
fmt.Println("HI")
}
Run the package from that folder:
go run .
Output:
HI
main.go calls demo(). Because demo.go is in the same directory and also declares package main, Go compiles both files as one package.
You can also list both files explicitly:
go run main.go demo.go
However, go run . is usually safer in real projects because it includes every non-test Go source file in the package.
Step by Step Execution
Consider this program:
// main.go
package main
func main() {
greeting := makeGreeting("Ada")
println(greeting)
}
// greeting.go
package main
func makeGreeting(name string) string {
return "Hello, " + name
}
Execution proceeds as follows:
go run .finds Go files in the current package.- Go compiles
main.goandgreeting.gotogether. - Execution starts at the single
main()function. main()callsmakeGreeting("Ada").makeGreetingreturns"Hello, Ada".printlnprints the returned string.
The source files are separate for organization, but their functions are available throughout the package.
Real World Use Cases
Splitting one package across files is common when files have different responsibilities:
- Command-line tools:
main.gostarts the program, whilecommands.goprocesses command arguments. - Web services:
main.goconfigures the server, whilehandlers.gocontains HTTP handler functions. - Data processing:
main.gocoordinates work, whileparser.goparses input andreport.gocreates output. - Small utilities:
main.gocalls helpers from files such asstrings.go,dates.go, orvalidation.go.
All of these files can remain in one package when their code belongs to the same component.
Real Codebase Usage
In real Go projects, developers usually split a package by responsibility while keeping closely related code together.
A common pattern is to keep main.go small:
package main
import "log"
func main() {
config, err := loadConfig()
if err != nil {
log.Fatal(err)
}
startServer(config)
}
Functions such as loadConfig and startServer may be in config.go and server.go, as long as all files use package main in the same directory.
For code intended to be reused by other directories, developers create a separate package. Its public identifiers begin with an uppercase letter:
// package message
func Greeting(name string) string {
return "Hello, " + name
}
The importing package can then call message.Greeting("Ada").
Common Mistakes
Defining main twice
A package can have only one main function.
// Broken: both files are package main and both declare main.
func main() {}
Remove the extra main and keep only helper functions in the other file.
Running only one source file
This command compiles only test1.go:
go run test1.go
If demo is in test2.go, Go reports an undefined function error. Run the full package instead:
go run .
Using different package names in one directory
This is invalid for ordinary Go source files in the same folder:
// one file
package main
// another file
package helpers
Use one package name per directory, except that external test files may use a _test package name.
Expecting lowercase functions to work across packages
Lowercase names are package-private. This works inside the same package:
func demo() {}
For another package to call it, export it with an uppercase first letter:
func Demo() {}
Importing a file name
Go imports packages, not individual .go files. You do not write an import such as import "test2.go".
Comparisons
| Situation | How to call the function | Must the function start with uppercase? |
|---|---|---|
| Same directory, same package | Call it directly: demo() | No |
| Different directory, different package | Import the package, then use pkg.Demo() | Yes, for external access |
Another main function in the same package | Not allowed | Not applicable |
Go test file (*_test.go) | Used by go test, not normal builds | Depends on package and test style |
package main is special because it builds an executable and needs one main() entry point. Other packages do not have a main() function; they provide reusable functions, types, and variables.
Cheat Sheet
// File: main.go
package main
func main() {
demo()
}
// File: demo.go
package main
func demo() {
// Available anywhere in this package.
}
# Run every buildable Go file in the current package
go run .
# Explicitly run selected files
go run main.go demo.go
- Files in the same directory with the same package compile together.
- Use exactly one
main()in a runnablepackage main. - Do not import another file in the same package.
- Lowercase names, such as
demo, are accessible only within their package. - Uppercase names, such as
Demo, are exported and can be used by importing packages. - Go imports packages, not files.
FAQ
Can Go files call functions from other files?
Yes. Files in the same directory with the same package declaration can call each other's package-level functions.
Why does go run test1.go say that demo is undefined?
That command compiles only test1.go. Use go run . to compile the entire package, or pass both file names.
Do I need to import test2.go?
No. Go does not import files. When both files are in the same package, their declarations are already shared.
Can I have two main functions in Go?
No. A compiled package main must have only one func main().
Why is demo lowercase?
Lowercase function names are unexported, meaning they are usable only inside their own package. That is fine when both files use package main in the same directory.
How do I call a function from a different Go package?
Place it in another directory, give it a package name, export the function with an uppercase first letter, import the package path, and call packageName.FunctionName().
Does file order matter in Go?
No. Go compiles the package as a whole, so demo.go does not need to appear before main.go.
Mini Project
Description
Create a small command-line greeting program split across two Go files. This demonstrates how main.go coordinates a program while another file provides reusable package-level logic.
Goal
Run a Go package where main.go calls a greeting function declared in another file.
Requirements
Requirement 1
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.