golang reference struct in same package in another file - go

How to reference MyStruct in another file in the same package or folder?
Currently I get undefined: MyStruct when go build lib/file_2.go. I can run go install with no error, should I just ignore the build error?
These are my files:
lib/file_1.go
...
package lib
...
type MyStruct struct{
}
....
lib/file_2.go
...
package lib
...
{
m MyStruct
}
....
Thanks

This command works for me
go run *.go
Actually this will compile all go file and run your main function. So this works well

You're asking the go tool to compile lib/file_1.go, you never mention lib/file_2.go so how is it supposed to know it should compile it?
From go help build:
Build compiles the packages named by the import paths,
along with their dependencies, but it does not install the results.
If the arguments are a list of .go files, build treats them as a list
of source files specifying a single package.

You should be able to use MyStruct directly, since it is in the same package as its definition.
If you have any issue, sometimes it can help (for an IDE like SublimeText + GoSublime, for instance) to do a go install before creating lib/file_2.go.
That way, lib/file_1.go is compiled and present in GOPATH/pkg, with lib/file_1.go definitions visible for lib/file_2.go to use during its compilation.

According to https://golang.org/doc/tutorial/getting-started, you should run:
go run .

You have to compile the multiple files using the build command first.
go build
Now you can see a build file got generated with the given name or the folder name in case of default. Then run the binary.
./binary_file_name

Related

go test fails with "can't load package build constraints exclude all Go files"

When I run this command
go test -tags integration $(go list ./... | grep -v /vendor/)
go fails with this for some packages that has all tests marked with // +build !integration
can't load package: build constraints exclude all Go files
Is there a way I can make go test ignore those packages in this case, instead of failing? Thanks
You will only get that error if all the files in the package are excluded by your build constraints, not just the test files. If that's what you want, just add a single package file with no code and the package will still be able to be loaded. For example, many packages put their package level docs in a separate file, which you could use to always have a valid package:
// Package foo does foo
package foo
For whatever it's worth : I was seeing similar errors while building my code. In my case, my main file had // +build go1.13 at the top of it and I was trying to get the file built using go1.12.x. Removing +build go1.13 fixed the issue.
The package you are importing might contain some source files with a conditional complication flag, which is a directive you may find at the top of the files like:
//+build linux darwin windows
package main
import "fmt"
func main() {
fmt.Println("hello")
}
The +build directive followed by one or multiple platforms indicates where this source code is supposed to be compiled on.
Therefore, you can simply try removing this directive to resolve the failure.
It worked for me.
Following on from snowfox's answer, if you can't remove the directive (becuase it was likely put there for a reason), you can still run the test by using the tag that was applied to that file (more info here).
If your file start looks like this:
//go:build bar
package foo
Then you can run the test by running go test ./foo_test.go --tags=bar

Struct from the same parent folder as main is not visible

I have a small go demo project in Gogland with the structure:
awsomeProject
->src
->awsomeProject
->configuration.go
->main.go
Configuration file has a simple structure just for demo:
configuration.go:
package main
type Config struct {
Data int
}
Main file just uses the Config struct:
main.go
package main
import "fmt"
func main(){
var cfg Config
cfg.Data = 1
fmt.Println("lalala")
}
The error that I have is:
/usr/local/go/bin/go run /Users/lapetre/Work/awsomeProject/src/awsomeProject/main.go
command-line-arguments
src/awsomeProject/main.go:6: undefined: Config
Process finished with exit code 2
Any idea why the Config is not seen in main?
Thanks
When you build reusable pieces of code, you will develop a package as a shared library. But when you develop executable programs, you will use the package “main” for making the package as an executable program. The package “main” tells the Go compiler that the package should compile as an executable program instead of a shared library. The main function in the package “main” will be the entry point of our executable program.
That's why you should use the following structure:
awsomeProject
->src
->awsomeProject
->configuration.go
->main.go
with main.go
package main
import "fmt"
func main(){
var cfg awsomeProject.Config
cfg.Data = 1
fmt.Println("lalala")
}
and configuration.go
package awsomeProject
type Config struct {
Data int
}
For more details:
https://golang.org/doc/code.html
https://thenewstack.io/understanding-golang-packages
How are you calling go run? If you're calling it like
go run main.go
then that's the problem.
Go run only runs the file(s) you tell it to. So you need to tell it to also run configuration.go, or if you have several go files to run you can use
go run *.go
as eXMoor suggested.
There are some limits/drawbacks to "go run *.go" however, so the better alternative is to use go build instead of go run.
go build
Will compile everything. Then, to run the executable:
./awesomeProject
To combine all of this into one command that will compile and run whatever app you're working on, you can use:
go build && ./${PWD##*/}
I have it aliased to
gorunapp
just to make it easier.
This may not actually be the answer to the problem you're having, but hopefully you'll find it useful information regardless.
Try to run your application with command:
go run *.go

"undefined" function declared in another file?

I'm trying to write a basic go program that calls a function on a different file, but a part of the same package. However, it returns:
undefined: NewEmployee
Here is the source code:
main.go:
package main
func main() {
emp := NewEmployee()
}
employee.go:
package main
type Employee struct {
name string
age int
}
func NewEmployee() *Employee {
p := &Employee{}
return p
}
func PrintEmployee (p *Employee) {
return "Hello world!"
}
Please read "How to Write Go Code".
Use go build or go install within the package directory, or supply an import path for the package. Do not use file arguments for build or install.
While you can use file arguments for go run, you should build a package instead, usually with go run ., though you should almost always use go install, or go build.
I just had the same problem in GoLand (which is Intellij IDEA for Go) and worked out a solution. You need to change the Run kind from File to Package or Directory. You can choose this from a drop-down if you go into Run/Edit Configurations.
Eg: for package ~/go/src/a_package, use a Package path of a_package and a Directory of ~/go/src/a_package and Run kind of Package or Directory.
If you're using go run, do go run *.go. It will automatically find all go files in the current working directory, compile and then run your main function.
You can try one of the following:
Method 1:
Assume that your project name is MyProject
Go to your path, run go build
It will create an executable file as your project name ("MyProject")
Then run the executable using ./MyProject
You can do both steps at once by typing go build && ./MyProject. Go files of the package main are compiled to an executable.
Method 2:
Just run go run *.go. It won't create any executable but it runs.
go run . will run all of your files. The entry point is the function main() which has to be unique to the main package.
Another option is to build the binary with go build and run it.
If you want to call a function from another go file and you are using Goland, then find the option 'Edit configuration' from the Run menu and change the run kind from File to Directory. It clears all the errors and allows you to call functions from other go files.
you should use go modules now, if you are not following How to write go code
With go module you don't have to put the code in the $GOPATH/src. it can live in any other location as well.
You can move the code to different directory like /employee, To make it work Just under employee directory initialise the go module
go mod init example.com/employee
I ran into the same issue with Go11, just wanted to share how I did solve it for helping others just in case they run into the same issue.
I had my Go project outside $GOPATH, so I had to turned on GO111MODULE=on without this option turned on, it will give you this issue; even if you you try to build or test the whole package or directory it won't be solved without GO111MODULE=on
While this doesn't directly address the OP's specific issue, I thought I'd chime in with the solution to my "undefined" error: the file with the undefined method had a build constraint (build tag).
More specifically, I accidentally included a build constraint to remove testing files from my deployed application binary in a utility function file used by my deployed binary. So in the OP's example - if employee.go had a build constraints their go build command would need to include a -tags flag matching the constraint in in order to have the file included.
For more info read this blog post:
https://dave.cheney.net/tag/build-constraints
Took a while to drill down my own MRE for this, so hopefully it will help others, despite being brief:
This can also occur if your functions / structs are defined in a file that has import "C", which will be silently ignored if CGO_ENABLED=0 is in your go environment, leading to you staring at a two file package that somehow is unable to share between themselves.
In GoLand,
right click a directory
GoLand will give you the option for build it and run it
it will also create a run configuration draft for you
you can save with an option of the upper right dropdown
If you right clic a file, it shows you commands to run, debug, test that file.
If you right clic a directory, it will be the same for that "package", expecting a main.go file inside the directory
I had a nasty import "C" in one of my go files.
If your source folder is structured /go/src/blog (assuming the name of your source folder is blog).
cd /go/src/blog ... (cd inside the folder that has your package)
go install
blog
That should run all of your files at the same time, instead of you having to list the files manually or "bashing" a method on the command line.
Off topic but still :-)
Before:
func NewEmployee() *Employee {
p := &Employee{}
return p
}
After:
func NewEmployee() *Employee {
return &Employee{}
}
No need to create a new variable. Just return.

Golang undefined variable

I have 2 go files:
/Users/username/go/src/Test/src/main/Test.go
package main
import "fmt"
func main() {
fmt.Printf(SomeVar)
}
and file /Users/username/go/src/Test/src/main/someFile.go
package main
const SomeVar = "someFile"
However I am constantly getting compiler error:
/Users/username/go/src/Test/src/main/Test.go:6: undefined: SomeVar
Can someone explain to me why is SomeVar labeled as undefined?
Try
go run Test.go someFile.go
Quote:
I think you're misunderstanding how the go tool works. You can do "go
build" in a directory, and it'll build the whole package (a package is
defined as all .go files in a directory). Same for go install, go
test, etc. Go run is the only one that requires you to specify
specific files... it's really only meant to be used on very small
programs, which generally only need a single file.
So do:
go build && ./program_name
See also
You code is correct:
someFile.go and Test.go belong to the same package (main)
SomeVar is a const declared at top level, so it has a package block scope, namely the main package block scope
as a consequence, SomeVar is visible and can be accessed in both files
(if you need to review scoping in Go, please refer to the Language Specification - Declarations and Scope).
Why do you get an undefined error then?
You probably launched go build Test.go or go run Test.go, both producing the following output, if launched from /Users/username/go/src/Test/src/main:
# command-line-arguments
./Test.go:6: undefined: SomeVar
You can find the reason here: Command go
If you launch go build or go run with a list of .go files, it treats them as a list of source files specifying a single package, i.e., it thinks there are no other pieces of code in the main package, hence the error.
The solution is including all the required .go files:
go build Test.go someFile.go
go run Test.go someFile.go
go build will also work with no arguments, building all the files it finds in the package as a result:
go build
Note 1: the above commands refer to the local package and, as such, must be launched from the /Users/username/go/src/Test/src/main directory
Note 2: though other answers already proposed valid solutions, I decided to add a few more details here to help the community, since this is a common question when you start working with Go :)
Due to landing on this page when I had a similar question, I'll include this answer alongside of what has already been stated. If you are using go run you may use:
go run . or go run .*
This question was also answered on this question
How to run all .go files within current directory through the command line (multi file package)

Build and reference my own local package in Go

I'm playing with Google Go and I'm having fun (!), but I'm having some problems with package subsystem.
I'm running Go 1.0.1 on Mac OS X Lion. I've build also various single file programs without problems (I've also build a small webapp using html/templates without problems and it compiles and runs without any error).
I've defined a "reusable" package (even.go):
package even
func Even(i int) bool {
return i % 2 == 0
}
func Odd(i int) bool {
return i % 2 == 1
}
and a consumer program (useeven.go):
package main
import (
"./even"
"fmt"
)
func main() {
a := 5
b := 6
fmt.Printf("%d is even %v?\n", a, even.Even(a))
fmt.Printf("%d is odd %v?\n", b, even.Odd(b))
}
But when I compile the "library" using
go build even.go
I got nothing... No errors, no message... What happens?
How should I do this?
The answer to your question, "How should I do this?" is explained in How to Write Go Code. It's really pretty important stuff and worth taking a look at.
The behavior of go build might seem puzzling, but is actually conventional for command line programs--no output means that the program ran successfully. So what did it do? For that your answer is in go help build
... Otherwise build compiles the packages but discards the results,
serving only as a check that the packages can be built.
What, you wanted more? Of course. "How to Write Go Code" explains good ways of doing this. For a quick fix to your program, I'll explain that the go command expects each package and each executable program to be in a separate directory. If you just make a directory called even, immediately under the location of useeven.go, and move even.go to it, then go run useeven.go should run just as you have it.
go build only generates an output file when it builds a "single main package". If you want to output a file for your other package you should use go install. That will build and install that package to your pkgs directory.
As noted in a comment by the OP, go build and go run useeven.go work fine, once you put even.go in its own folder: ./even/even.go. There is a bit of Go magic in the ./ (in the import) that makes the "local package" build automatically without requiring it to be installed anywhere.
useeven/
├── even
│   └── even.go
└── useeven.go
If you wanted to make this work without the magic ./, then the library need to be installed. A quick-and-dirty way (at the risk of polluting your library namespace) of making this work for your project is to simply register the library's source location by using a symbolic link like so (in this example GOPATH is ~/go):
[ useeven ]
$ ln -s $(pwd)/even ~/go/src
Now when you build the program, it automatically performs a go get even to install an up-to-date version of your library.
Note that this doesn't make go install* work for the library, it just makes doing that unnecessary.
There are more idiomatic ways of doing this, if you're not in a hurry: How to import local packages in go?
The reason that output is not being generated here is because you're running the
go build even.go
command on the package and not the main go file. Doing so on the package will check for errors on the package, but because it's not a main with an output, no success messages will be generated. If there are issues with the package's contents, errors will be displayed, otherwise if it compiles fine there will be no output
Instead, you should run:
go build useeven.go
To create the binary, then to execute the binary and get output from the program:
./useeven

Resources