Import a Struct from Another File or Package in Go

Deepak Prasad
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.

text
demo/
├── go.mod
├── main.go
└── models.go

models.go:

go
package main

type User struct {
	Name string
	Age  int
}

main.go:

go
package main

import "fmt"

func main() {
	u := User{Name: "Alice", Age: 30}
	fmt.Println(u)
}
Output

Run the package from the module directory:

bash
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:

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:

bash
go run main.go

Go compiles exactly the files you named. models.go is not included, so User is missing:

output
# command-line-arguments
./main.go:6:7: undefined: User

Use the package command instead:

bash
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:

bash
go run main.go models.go

That 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:

bash
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:

text
demo/
├── go.mod
├── main.go
└── models/
    └── user.go

go.mod:

text
module example.com/demo

models/user.go:

go
package models

type User struct {
	Name string
	Age  int
}

main.go:

go
package main

import (
	"fmt"

	"example.com/demo/models"
)

func main() {
	u := models.User{Name: "Alice", Age: 30}
	fmt.Println(u)
}
Output

Run from the module root:

bash
go run .

Sample output:

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:

go
type User struct {
	Name string
}

This type is not exported:

go
type user struct {}

This type is exported but the field is not:

go
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.

text
module example.com/demo

with directory:

text
models/

gives import path:

text
example.com/demo/models

The 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


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.


Frequently Asked Questions

1. Do I need to import another Go file in the same folder?

No. Files in the same package are compiled together. Go imports packages, not individual .go files.

2. Why does go run main.go not see my struct in another file?

go run main.go supplies only that source file to the compiler. Run go run . to build the whole package in the current module directory, or list every file explicitly.

3. How do I import a struct from another package?

Import the package path from go.mod, then use models.User where models is the package name and User is an exported type starting with a capital letter.

4. Does the struct name need to start with a capital letter?

Only when another package must access the type. Within the same package, lowercase names are visible across files in that package.

5. Do struct fields also need capital letters?

Yes, if another package must read or set them directly. Unexported lowercase fields are only accessible inside the package that defines them.

6. Can two Go files in the same directory use different package names?

Not for ordinary source files built into one package. All non-test .go files in a directory must declare the same package name.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise spanning these technologies, he develops robust solutions and implements efficient data processing and management strategies across various projects and platforms.

  • Go (programming language)
  • Python (programming language)
  • Java (programming language)
  • MongoDB
  • Kubernetes