Call a Function From Another Package or File in Go

Call Go code from another file or another package: what to import, when you do not need an import, capital letters for public functions, and how to fix typical errors.

Published

Updated

Read time 7 min read

Reviewed byDeepak Prasad

Call a Function From Another Package or File in Go

In Go you do not import a single function by name. You import a whole package (a folder of related code), then call the function you need through that package—much like you already do with fmt.Println or strings.Trim.

If you are splitting one project across several files, or you built a helper folder and now want main to call into it, the ideas below are what you need. For a refresher on writing functions themselves, see golang function.

Tested on a recent stable Go toolchain on Linux.


Same folder vs another folder

Think of it in two situations:

  • Another file, same folder (same package): every .go file in that folder shares one package ... line at the top. They already see each other’s functions—no extra import between those files. If the function should stay private to that folder, start its name with a lowercase letter. If other folders need to call it, start the name with an uppercase letter.

  • Another folder (another package): add that folder’s path in an import, then use the name from that import line, a dot, and the function—similar to greet.Hello() in the example below. Only names that start with an uppercase letter can be called from outside that folder.

You already follow this when you write import "strings" and then strings.ToUpper: you imported the strings package, not “ToUpper” by itself.


Example: call code from the standard library

Here main uses strings.ToUpper from Go’s built-in strings package. The import block lists which packages this file uses; inside main you write the package name, a dot, then the function name.

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ToUpper("golang"))
}
Output
text
GOLANG

When you add your own helper folders later, you will do the same thing: add the folder to import, then write the package name, a dot, and the function you want—just like strings.ToUpper here.


Example: two functions in one program

Imagine greet lives in helpers.go and main lives in main.go, both with package main at the top. They behave like this one file: main calls greet directly—no import between them, because they are the same package.

go
package main

import "fmt"

func greet(name string) string {
	return "Hello, " + name
}

func main() {
	fmt.Println(greet("Ada"))
}
Output
text
Hello, Ada

If you rename greet to Greet (capital G), other files in package main can still call it. If this were a library package (not main), that capital letter would also let other packages call Greet.


Same package, more than one file

On your machine the layout might look like this:

text
.
├── go.mod          # module example.com/demo
├── main.go         # package main
└── counter.go      # package main

Both files use package main. Anything you declare in counter.go is visible in main.go without importing the other file—Go treats all .go files in that folder as one unit.

go
// counter.go
package main

import "sync"

var mu sync.Mutex
var n int

func Next() int {
	mu.Lock()
	defer mu.Unlock()
	n++
	return n
}
go
// main.go
package main

import "fmt"

func main() {
	fmt.Println(Next(), Next())
}
bash
go mod init example.com/demo
go run .
text
1 2

This example is split across files, so run it on your computer: create the files, run go mod init once in that folder, then go run ..


Calling a helper folder from main

Use a clean folder for this part (or delete the earlier example files) so you only have one main.go in the root.

Say your module is example.com/demo and you add a subfolder greet with its own package greet. From the root you import the path example.com/demo/greet—that path comes from your go.mod module line plus the folder name, not from the .go filename.

go
// greet/greet.go
package greet

import "strings"

// Hello is exported (capital H) so importers can call greet.Hello.
func Hello(name string) string {
	return "Hello, " + strings.TrimSpace(name) + "!"
}
go
// main.go
package main

import (
	"fmt"

	"example.com/demo/greet"
)

func main() {
	fmt.Println(greet.Hello("  Sam  "))
}
bash
go mod init example.com/demo
go run .
text
Hello, Sam!

In practice you import the folder’s path (what you would put in import), then call something like greet.Hello using the name you chose in the import list.

If the package name is awkward

You can pick a shorter alias in the import:

go
import (
	hook "example.com/demo/twiliohook"
)

// Then call hook.Validate(...) instead of typing the long path each time.

Bigger example: main and a methods folder

Here the heavy logic sits under methods/, and main only wires the command line. Everything uses the Go standard library only, so you only need a normal go.mod—no extra downloads.

Create methods/methods.go and root main.go as below. Your go.mod should start with module example.com/demo (or change the import in main.go to match whatever module name you chose).

go
// methods/methods.go — package name matches directory
package methods

import (
	"fmt"
	"regexp"
	"sort"
)

type data struct {
	key   string
	value int
}

// AlphabetsOnly is exported for use from other packages.
func AlphabetsOnly(str string) string {
	match := regexp.MustCompile(`[^a-zA-Z]+`)
	lettersOnly := match.ReplaceAllString(str, "")
	maxVal := make(map[string]int)
	for _, ch := range lettersOnly {
		maxVal[string(ch)]++
	}
	results := []data{}
	for key, val := range maxVal {
		results = append(results, data{key: key, value: val})
	}
	sort.Slice(results, func(i, j int) bool {
		return results[i].value > results[j].value
	})
	fmt.Printf("All Elements are: %v \t \n", results)
	if len(results) == 0 {
		return ""
	}
	return fmt.Sprintf("Most frequent character is %s", results[0].key)
}
go
// main.go
package main

import (
	"fmt"
	"os"

	"example.com/demo/methods"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("usage: go run . <string>")
		return
	}
	fmt.Println(methods.AlphabetsOnly(os.Args[1]))
}

From the folder that contains go.mod and these files:

bash
go run . rmysyuio0393839ftsy
text
All Elements are: [{y 3} {s 2} {r 1} {i 1} {o 1} {f 1} {m 1} {u 1} {t 1}] 	 
Most frequent character is y

Because this program reads a command-line argument and uses two packages, run it on your machine with go run . as shown—not as a single pasted snippet.

For how go.mod fits together, see create custom Go module in Go.


Errors you might see

  • undefined: foo.Bar: either Bar starts with a lowercase letter (so other packages cannot see it), or it does not exist in foo. Capitalize the name if it should be public.

  • could not import example.com/...: the path in import does not match your go.mod module line plus folders, or you are running go from the wrong directory. go mod tidy often helps after renames.

  • import cycle not allowed: two packages are importing each other in a circle. You usually fix that by moving shared bits into a third package, or by passing data one way through a smaller interface.

  • package main in a library folder: library code normally uses a package name that matches the folder (not main). Reserve package main for the program you actually run.


Unit tests and mocks (short note)

If you landed here from “mock a function in another package,” the usual approach is to depend on a small interface in your code, then supply a fake implementation in tests. Libraries like testify/mock help with that pattern. This article stays on day-to-day imports; add tests once your calls compile.


Summary

Same folder and same package line means your files already share functions—no import between them. A different folder is a different package: add the right import, then call the function with an uppercase name from the other package. The early strings / greet examples work the same way as fmt.Println in your own programs; the bigger layouts you run with go run . from the project folder. For more on functions in general, see golang function. For the official tour of calling code across modules, see Call module code on go.dev.


References


Frequently Asked Questions

1. Do you import a function in Go?

No. You import a whole package (for example fmt or example.com/lib/mypkg). Then you call a function from that package like mypkg.DoWork(), with a capital letter in DoWork if other packages are allowed to call it.

2. How do I call a function from another file in the same package?

Put both files under the same package line (for example package main or package handlers). Any top-level function in that package is visible to all files in the package; no extra import is needed. Only the first letter of the name decides whether other packages can see it.

3. Why is my function undefined from another package?

Common causes: the function name starts with a lowercase letter (so only its own package can use it), the import path does not match your folders and go.mod line, or you ran go from outside the module. Read the compiler message—it usually points to the exact line.

4. What is the difference between package main and a library package?

package main together with func main() is what you use for a program you run from the terminal. Other folders use a package name that matches the folder; they hold reusable code that main (or other packages) imports. Those folders do not use their own func main as the library entrypoint.

5. Can I run the multi-file examples in the browser?

Treat them like a normal project on your machine: put the files in one folder, make sure go.mod matches the imports, and run go run . in a terminal. The short programs at the beginning are small enough to copy as one file if you just want to try the idea quickly.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …