| Tested on | RHEL 10.2 with Go 1.27.0 |
|---|---|
| Package | Go modules (go.mod) and standard go tool (Go 1.27.0) |
| Applies to | Any host with Go installed |
| Privilege | Normal user |
| Scope | Use a struct from another file in the same package, import an exported struct from another package, fix undefined errors from go run main.go, and export rules for cross-package access. Does not cover full module path design for local packages. |
| Related guides | Getting started with Go go.mod file not found Create a custom Go module Golang declared and not used Cannot find package even if GOPATH is set |
Go does not import another .go file. Files in the same package are compiled together. When the struct lives in a different package, you import that package and use its exported name.
| Struct location | What to do |
|---|---|
| Another file, same package | No import required |
| Different package | Import the package path from go.mod |
| Different module | Import its module path; use go.mod / workspace to make it available |
Beginners usually hit one of three situations: User lives in models.go beside main.go, User lives in a models package folder, or the code looks correct but go run main.go reports undefined: User. The sections below map each case to the fix.
Use a struct from another file in the same package
When main.go and models.go both declare package main, they share one namespace. The User type in models.go is already available in main.go.
demo/
├── go.mod
├── main.go
└── models.gomodels.go:
package main
type User struct {
Name string
Age int
}main.go:
package main
import "fmt"
func main() {
u := User{Name: "Alice", Age: 30}
fmt.Println(u)
}Run the package from the module directory:
go run .go mod init example.com/demo creates the module before the first run if you are starting from an empty folder. The module path in go.mod does not affect same-package file access, but you need a module for the modern go command workflow on current Go releases.
Sample output:
{Alice 30}You do not write import "models.go". Go imports packages, not individual files.
Both files must declare the same package name (package main in this example). If one file used a different package name in the same directory, the compiler would reject the mix unless the file is a test file with a _test suffix.
Why go run main.go says undefined: User
If User is defined in models.go but you run only the main file:
go run main.goGo compiles exactly the files you named. models.go is not included, so User is missing:
# command-line-arguments
./main.go:6:7: undefined: UserUse the package command instead:
go run .That runs the complete main package in the current directory instead of only the file you named.
You can also list files explicitly when you truly need to name them:
go run main.go models.goThat compiles both files into one main package build, so User resolves. Listing every file by hand becomes awkward as the project grows, which is why go run . is the usual workflow.
For day-to-day work, go run . is the normal choice. The same rule applies when you build a binary for the whole package:
go build .That builds the whole main package from the applicable .go files in the directory, rather than compiling only main.go.
Importing models.go does not fix the go run main.go error. The problem is which source files were passed to the compiler, not a missing import statement.
Import a struct from another package
Move the type into its own package when you want a separate namespace:
demo/
├── go.mod
├── main.go
└── models/
└── user.gogo.mod:
module example.com/demomodels/user.go:
package models
type User struct {
Name string
Age int
}main.go:
package main
import (
"fmt"
"example.com/demo/models"
)
func main() {
u := models.User{Name: "Alice", Age: 30}
fmt.Println(u)
}Run from the module root:
go run .Sample output:
{Alice 30}You import the package containing the type and reference an exported identifier through that package name (models.User). You are not importing the struct as a separate import path.
The directory name (models) does not have to match the package name, but keeping them aligned avoids confusion. The import path always comes from go.mod plus the folder path, not from the struct name.
Export structs and fields to another package
Capitalization controls visibility across package boundaries.
This type and field are visible outside models:
type User struct {
Name string
}This type is not exported:
type user struct {}This type is exported but the field is not:
type User struct {
name string
}Another package can use models.User but cannot read name directly.
Within the same package, unexported names are accessible across different files in that package. The capitalization rule matters when code in another package needs access.
Exported methods follow the same rule: a method named DisplayName can be called from another package; setAge on an unexported receiver type stays internal to the package.
Import path comes from go.mod
Modern Go uses modules. The import path for a local package combines the module path with the directory name.
module example.com/demowith directory:
models/gives import path:
example.com/demo/modelsThe compiler resolves that path through go.mod, not through GOPATH src layout. If you see package ... is not in std, the import string usually does not match your module path.
Historical GOPATH projects used paths under $GOPATH/src, but module-based projects should always start from the module line in go.mod. For designing import paths across multiple local packages, see create a custom Go module rather than treating this page as a full import-path guide.
Common errors
Most undefined-struct reports come from one of the patterns below rather than a missing import of a .go filename.
| Error or problem | Cause |
|---|---|
undefined: User after go run main.go |
Only main.go was supplied; use go run . |
undefined: models.User |
Type is unexported, or import path or package name is wrong |
u.Name undefined |
Field is unexported (lowercase) |
package ... is not in std |
For a local package, first check that the import path matches the module path in go.mod plus its subdirectory |
| Two package names in one directory | Non-test .go files in a directory must share one package name |
Trying import "./models" |
Relative filesystem imports are not the normal module model |
References
- The Go Programming Language Specification — Packages
- The Go Programming Language Specification — Exported identifiers
- Go Modules Reference
- Command go — run
Summary
Same package, same directory: put the struct in another .go file and use it directly. No import is required because Go compiles all files in the package together. This answers the common search "golang use struct from another file" when both files share package main.
Different package: import the package path from go.mod and use models.User for an exported type. Capital letters mark types and fields that other packages can access. You import the package namespace, not the struct name as its own import path.
When undefined: User appears after go run main.go, the fix is usually go run . so Go runs the complete package instead of only the named source file. That failure mode is easy to miss because the struct is visible in the editor but omitted from the compiler invocation.
Match the scenario—same package versus different package—before reaching for import.

