71

My project structure is like this.

packagetest/
    main.go
    lib.go

In main.go, I have this code.

package main

import "fmt"

func main() {
    fmt.Println("Hello from main.go.")
    Test()
}

While in lib.go, I have this code.

package main

import "fmt"

func Test() {
    fmt.Println("This is the Test function in lib.go.")
}

When I try to compile with go build main.go, I get ./main.go:7: undefined: Test. Is this way of structuring my code possible?

425nesp
  • 6,936
  • 9
  • 50
  • 61
  • Possible duplicate of [How can I "go run" a project with multiple files in the main package?](https://stackoverflow.com/questions/28081486/how-can-i-go-run-a-project-with-multiple-files-in-the-main-package) – jk2K Sep 26 '19 at 01:24

9 Answers9

80

Try running just go build. When you give it a go file as an argument, it will not look for other go files. You can also do go build *.go

Stephen Weinberg
  • 51,320
  • 14
  • 134
  • 113
  • 2
    for those who might have the same issue as me: note that the definitions in `main_test.go` won't be visible to `main.go`. (But why would you try to access them right?) – totooooo May 15 '20 at 17:00
25

This is an old post but it didn't answer my issue clearly, so I'm posting for the benefit of others in the future.

When run go run --help you will find this manual:

Run compiles and runs the main package comprising the named Go source files. A Go source file is defined to be a file ending in a literal ".go" suffix.

By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.

go run <filename.go> is used for small programs with just a few files. With several files you will run into an issue where your main.go cannot find other files because go run doesn't compile and link them implicitly unless named. That's why go build the project works.

Alternatively, go run *.go (building all files) should work most of the time.

Pandemonium
  • 7,724
  • 3
  • 32
  • 51
  • 7
    When I ran : `go run *.go`, It says: `CreateFile *.go: The filename, directory name, or volume label syntax is incorrect.` (go version go1.10 windows/amd64, Windows 10 x64) – Dentrax Mar 14 '18 at 09:55
9

On the golang.org webpage you can read about the build command that:

If the arguments are a list of .go files, build treats them as a list of source files specifying a single package.

So, go build main.go will treat main.go as a single package. Instead, you should use:

go build

to include all files in the folder.

ANisus
  • 74,460
  • 29
  • 162
  • 158
8

This problem will happen when go cannot find your other file (like lib.go in this example).

If you use JetBrains Goland , you should change your "Run kind" to "Directory". Goland will help you to do these:

  • go build .
  • run this execution file.

If you use JetBrains Goland , you can contrast the difference between "Run kind".enter image description here

When i select "File", and then run, you will see the message on the console, like this:

GOROOT=C:\Go #gosetup
GOPATH=C:\Users\hgs\go #gosetup
C:\Go\bin\go.exe build -o C:\Users\hgs\AppData\Local\Temp\___go_build_select_go__4_.exe "C:/Users/hgs/Google Drive/My Maps/computer/2.programming_lang/Golang/source-code-refer/basic/select.go" #gosetup
# command-line-arguments
.\select.go:14:16: undefined: Add

When you select "Directory" and select your directory, and then run, you will see something like this:

GOROOT=C:\Go #gosetup
GOPATH=C:\Users\hgs\go #gosetup
C:\Go\bin\go.exe build -o C:\Users\hgs\AppData\Local\Temp\___go_build_basic_.exe . #gosetup
C:\Users\hgs\AppData\Local\Temp\___go_build_basic_.exe #gosetup
...
Jess Chen
  • 3,136
  • 1
  • 26
  • 35
7

You can also try below command if you don't want to build but simply execute it :

go run main.go lib.go
Shashank Vivek
  • 16,888
  • 8
  • 62
  • 104
3

If using multiple files for Go main pkg, instead of single file path as go run main.go, go require main pkg dir in the run or build command, like:

#from outside packagetest dir
go run ./packagetest/
go build ./packagetest/

#from within packagetest:
go run ./
go build ./
Karan
  • 309
  • 3
  • 8
3

Run all the file then able to call

go run *.go

or

go run main.go lib.go
Amit Kumar
  • 1,503
  • 14
  • 11
2

I think the problem is you can only have one file using package main.

Try putting lib.go in a different package. This requires:

  1. lib.go to exist in a folder with the same name as the new package (e.g., myLibs).

  2. Adding the package name to lib.go (package myLibs).

Then, in main:

import myLibs
call myLibs.Test()
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Briank
  • 161
  • 1
  • 5
1

For others who may need this.

I had a similar issue. However, my problem was that the function I wanted to call was in a my_test.go file, and I was trying to call it from a file that was not called *_test.go but testutils.go. (Maybe someone will tell me not to have a testutils.go file?)

jcfollower
  • 3,103
  • 19
  • 25