Why the functions defined in other "main" packages are not recognised? - go

I have to files main.go and main2.go . In main.go I have the main() function defined along with a call somefunc() which is in main2.go. The issue is that when I run go run main.go it says that somefunc() is undefined. Basically it doesn't scan the other main functions from package. However if I declare this somefunc() in main.go it works but when I run go test it says the function is redeclared.
Question: Is there any way that I can tell to go run to behave like go test and compile/run all the files from the package(in this case both main.go and main1.go) not just main.go?

You must include all the files as argument of the go run.
go run main1.go main.go
or
go *.go
Unless there are test files in the same folder.

Related

How to test library functions in Golang

I'm learning Go so I'm writing some basic utils and libraries for fun that I can reuse in other modules.
When importing them inside another module (using go get for example), I can use them just fine.
As I understand, Go will look for a package main and a main function to know the entrypoint when trying to run a go app/module.
The thing is that the libraries are not in "package main", not in main.go and have no main function, so how am I supposed to use the cli and use go run . to test the behavior of my function?
Do I absolutely need to create another module with a main.go file inside a package main?
Or do I need to create a test file and use go test ?
Thank you!
Non-main packages (i.e., library packages) are not runnable.
To run the code in them, you must either run a main package that imports and runs their code, or write test functions in _test.go files to run the code. Note that test files are not just for unit tests; you can write whatever you want in them, and they can often be easier than creating a new main package for testing.
Modern IDEs now will allow you to easily run individual tests in debugging mode, so you can step through your code and see if it's working how you expect. If you prefer print debugging and doing everything from the command-line, you can still run an individual test and see the print output like this:
// something_test.go
package mylibrary
func TestSomeFunction(t *testing.T) {
SomeFunction()
}
go test mylibrary -v -run TestSomeFunction
go test is the preferred way to test Go code.
If you do not want to use go test for some reason, then use build constraints and the go run command to execute a main program from the same directory as your package.
Here's an example program with a build constraint. Place the file in the same directory as the package source files. The comment //go:build ignore is a build constraint that excludes the file from the package sources.
//go:build ignore
package main
import (
"your/package/import/path" // <-- modify to your path
"fmt"
)
func main() {
// do something with your package here.
fmt.Println("example")
}
Assuming that the above file is named program.go, run the program from the package directory with the command:
go run program.go
The go run command is OK for running toy or test programs like this. Prefer the go build command for anything else.

Difference between go run ./path/dir and go run path/dir

Note: This is not asking Why the functions defined in other "main" packages are not recognised?.
I've got a project with the following structure:
go/src/github.com/me/project/cmd/web/main.go
# main.go
package main
import(
"github.com/me/myproject/internal/myproject"
)
void main() {
// ...
}
go/src/github.com/me/project/cmd/web/handlers.go
# handlers.go
package main
void someFunc() {
// ...
}
And I compile and run successfully with:
go run ./cmd/web
I can also run successfully with go run cmd/web/*.go
However, when I try to run with go run cmd/web, why does compilation fail with the output:
package cmd/web: package cmd/web is not in GOROOT (/usr/local/go/src/cmd/web)
Why does ./cmd/web work, but cmd/web does not?
When you run ./cmd/web, you refer to the correct directory in your current directory tree.
cmd/web however refers to a package living where the stdlib packages are. If you try to run this example
go run net/http
It will tell you that it can't run it because its not a main package. It has found the stdlib net/http package with that name; but since cmd/web doesn't exist it doesn't work

Incorrect package name not throwing error on build

Considering the sample hello world with the wrong package name with the file named as main.go
package test
import "fmt"
func main() {
fmt.Println("hello world")
}
on go build main.go the build doesn't work (doesn't generate the executable) because of the incorrect package name. But why no error is thrown?
A package name test is not incorrect, it is valid according to Spec: Package clause:
PackageClause = "package" PackageName .
PackageName = identifier .
test is a valid Go identifier.
As to what does go build main.go do?
Generally you list packages to go build, but you may also list .go source files, just as in your example.
Quoting from go help build:
If the arguments to build are a list of .go files, build treats them as a list of source files specifying a single package.
So go build simply built your test package, consisting of a single main.go source file. It is not an error to add a main() function to a package that is not main.
As to why "nothing" happens: go build generates no output if everything is ok, and it outputs error if something is not right. go build applied on a non-main package just "checks" if the package can be built, but it discards the result. Please check What does go build build?

Goland doesn't see functions from another file

I have main.go file
package main
func main() {
func2()
}
func2 is defined in file2.go:
package main
func func2(){
...
}
Everything is OK when I compile and run it from a command line:
go run main.go file2.go
But when I run it from Goland by pressing RUN it gives me an error:
# command-line-arguments
./main.go:95: undefined: func2
How should I overcome it?
Go to Run | Edit Configurations and change the run configuration Type to point from File to a Package, then the package name must be fully qualified (for example github.com/user/package).
Edit:
You can also right-click on the folder and then select Run | go test <folder name>. This will create a run configuration of the type Directory.
Note: there are differences between the Directory and Package type configurations.

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

Resources