GO (Golang) does not see other .go files inside the same dir - go

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!

Related

Deploying Go subpackages to Google Cloud Functions fails

I'm trying to deploy a function to GCF but it's failing no matter what I try. This is the error returned every time:
Build failed: 2021/03/02 18:02:46 Unable to extract package name: unable to find Go package in /workspace/serverless_function_source_code.
exit status 1; Error ID: aba1aa6a
I've read a few answers here and I tried to fix the issue as told, but I keep having this error and I'm lost at this point.
My project structure is as follow:
.
|--function.go
|--go.mod
|--go.sum
|--subpackage
` |--subpackage.go
My main function uses some stuff from subpackage.go and the function.go import is:
package function
import (
"fmt"
"log"
"net/http"
// remote imports //
modname/subpackage
)
and then the go.mod file:
module modname
go 1.13
require (
// remote imports //
modname/subpackage
)
The subpackage is initialized as package subpackage and I think this is what the GCF docs say.
In function.go I have a function called Start that I indicated as the entrypoint in the setup. I'm lost and I have no idea how to work around this.
Ok, found the problem. If you have my issue, ignore the go.mod file in my question, as it was rigthly suggested on an other answer that you should not include the local packages.
But my problem wasn't that. I was zipping and uploading the FOLDER containing the project, not the file inside the folder. GCF than unzipped the .zip and found an other folder with the project inside.
Your go.mod and function.go files have to be at the first level. Hope this will save time for someone else.
Delete the reference of your subpackage in your go.mod file. When the subpackage is bellow the function.go file you don't need to reference it in the go.mod file.

Project structure and importing packages

I'm just starting to learn Go and I'm wondering how to best organize my project and import packages. I created a project at $GOPATH/src/my_project. It contains the file main.go and the folder foo containing the file bar.go.
$GOPATH/src/my_project
main.go
foo/
bar.go
My main.go looks as follows
package main
import (
"./foo"
"fmt"
)
func main() {
fmt.Println("Main")
foo.Baz()
}
Here is the foo.go
package foo
import "fmt"
func Baz() {
fmt.Println("Baz")
}
It works the way I expect it to, but I wonder if this is really the right way to structure a project and import packages, because most tutorials only import packages from github and never from local.
Thanks for your answers..
Relative imports are possible in Go but they are not encouraged to be used.
Instead you always use the full path of the package. In your case that would be my_project/foo. This is is relative to the GOPATH/src folder.
However, since we have Go modules now which make things a tiny bit more complicated to start with but have a lot of advantages in the long run.
Just earlier today I gave a step by step guide on how to set up a new project with Go modules: After go install the import doesn't recognize the package
The module name in this guide is the basis for your project then and all paths in the module build on that path. Let me give an example:
Let's say you name your module github.com/yourName/myProject. Then you can import the subpackage foo with github.com/yourName/myProject/foo.
Note: The module path should be the same as the git URL, that way you can just get the module with go get. If you don't plan on ever uploading the project to github or another git URL, you should still choose a unique name. Starting with a domain you own is a good idea -- for uniqueness.

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.

How to use multiple .go files in the same application

Good Morning All,
I am new to Golang. I want to move some of my functions out into separate files so that I will not have like a 10,000 line .go file at the end. lol. I created two files both have the same package called main. Do I need to change package name to be app specific? Anyway how do I get these two files to talk?
Example:
MainFile.go:
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello World!")
Test()
}
NewFile.go:
package main
import (
"fmt"
)
func Test() {
fmt.Println("Hello World Again!")
}
The test method is in the second file but cannot be reached by the first. I am sure this is some rudimentary thing I am missing.
Thanks
Update:
I tried specifying this on the command line: go build MainFile.go NewSourceFile.go. It comes back with no errors but never builds the binary. How do I get it to output the binary now?
If you run go run MainFile.go, Test() won't be found because its not in that file. You have to build the package then run the package:
Inside the folder where the 2 files are, run go build and you will get a binary in that folder. Then just run the binary: ./MyPackage

Resources