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
Related
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.
PROBLEM: functions exported from other packages are undefined, invisible from inside of main.go
SOLUTION:
Put main.go into a separate folder (name it app or main, doesn't matter). Only go.mod remains in root, with the folders "app" and "package1" "package2" etc. After this VSCode automatically added imports on save, I didn't even need to do anything. If I have main.go in root then it doesn't work (most of the time) as it doesn't "see" functions from other modules (undefined).
I found the solution HERE,(see post by davidbost). The solution on this page by Andrey Dyatlov worked too for a while and then stopped working.
It took me probably 10 hours of try and error and searching.
Hopefully the above will help others. Thank you, everyone!
_______________________________________________________________________
Original Problem Description:
Windows 10, Go 1.17, VS Code with Go extension.
Hello, I am new to Go and I was not able to follow a single tutorial due to the following issue. When I create another .go file in the same directory (or inside a folder of the same directory) as the main.go, I receive error saying .\main.go:7:2: undefined: SayHi
main.go file:
package main
import "fmt"
func main() {
fmt.Println("1st")
SayHi()
}
another .go file inside /something folder:
package something
import "fmt"
func SayHi() {
fmt.Println("Hi!")
}
Running go run main.go results in the undefined SayHi error
I googled the issue with no luck.
$ go build // gives out the same error
$ go install // gives out the same error
without using functions from other files $ go run main.go runs just fine.
I also tried go init with adding my github directory with no luck (by following a tutorial). I also tried the official starting guide with go run init, and the exported Capitalized function is still undefined. What's worse is that autocomplete for the SayHi function works, yet it won't compile because undefined.
I have set PATH to C:\Users\xxx\go and put my files there, I also tried using C:\Go with no luck, it's still undefined. I'm about to give up on Go...
It' would be hard to fix your project without knowing its current state. Please, try to start from scratch:
Create a directory for your project anywhere outside $GOPATH:
mkdir myproject
cd myproject
Run the following command to create a go.mode file that describes your project (module) and its dependencies; let's call the module github.com/me/myproject:
go mod init github.com/me/myproject
Create the first file; let's call it main.go:
package main
import "fmt"
import "github.com/me/myproject/something"
func main() {
fmt.Println("1st")
something.SayHi()
}
Create a directory for the package called github.com/me/myproject/something:
mkdir something
Create a file with path something/something.go:
package something
import "fmt"
func SayHi() {
fmt.Println("Hi!")
}
From the myproject directory, run go build.
Launch your first Go program:
./myproject
1st
Hi!
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?
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.
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