Golang plugin on Intellij. Library and break points - go

I write my code on Go. I build my project in Idea Intellij with plugin for golang. I have a package main. In main import different packages.
import (
"RF"
"flag"
"io"
"net/http"
"os"
"runtime"
"depot"
"info"
"logger"
"logic"
"poly"
"ranker"
"revgeocoder"
"search"
"search/engine"
"stat"
"views"
"fmt"
)
This packages very well linked if I write paths in $GOPATH. In Idea Intellij it makes such way:
Now, I want:
Build my project without warning
Debugging my project
First point. I make a 'build' and than I have: "Package is not specified"
If I write to Package name main, than warning doesn't disappear:
What I can do?
Point number two. The assembly is successful. After that part of package I can debug, another package I cannot debug. For example package engine I can debug. Path to this package:
/home/INT.PV.KM/urvanov/hedgehogues/distr/mapsfullsearch/src/search/engine/engine.go
Next file I cannot debug.
/home/INT.PV.KM/urvanov/hedgehogues/distr/mapsfullsearch/src/search/context.go
I cannot set a breaks point in this file:
Please, help me with my problems.

Build my project without warning -> you need to use the full package name (for example you need to use "github.com/dlsniper/demo" for a package under the GOPATH /home/florin/go and full path $GOPATH/src/github.com/dlsniper/demo. Alternatively, you can use the Run Kind directory and point it to the directory or simply just use the green arrow near the func main, click on it, select Run ... and then select Go Application
Debugging my project -> once you get your Run Configuration of type Go Application to run the application then to debug it you'll just need to use the Debug option instead of Run. Alternatively, you can click on the green arrow near the func main and choose Debug... to debug your application.

The answer to the first question
Any project in Go consist of packages. There is nothing except for packages. All packages are located in the same directory, which one is project. Other directories are libraries. They set through environment variable $GOPATH. IDEA IntelliJ let make it as:
File->Settings:
There are two type of libs in Go: globals and locals. You read about this here.
In the build time is necessary to specify which package we want to gather and line up all the dependencies themselves. In my project, there are n packets. For example, I can build mapsfullsearch package. I can build mfsimporter package. Or I can build any other, in which there is func main () {/*...*/}. To build just specify the appropriate configuration.
After that, all Imports (if relevant packages exist), resolved.
About configurations. Go to Run -> Edit Configurations...
Name: name of compilled file.
Run kind: which type of building (file or package).
Package: package name that matches the name of the directory in which the main(). There are drop-down list in IDEA IntelliJ. It appears, if you start to write his name.
Output directory: directory where the binary.
Environments: variables of environments
Go Tool arguments: compiler's arguments
Program arguments: program's arguments
For more information about config can be read here.
The answer to the second question
In the IDEA may be poorly specified file path. In that case, to which I referred in her question, the problem was related to the fact that the path to the library is specified via the home directory, which is denoted by ~. IDEA does not perceive such format. Repeat this problem I did not succeed. Although up to the moment until I put the project in the root file system, my project didn't work.

Related

Understanding How to Build Go Source

I am confused about how to layout my Go project and then how to build it. I am reasonably new to Go and believe there was a time <1.13 where the GOPATH was important. I am using 1.14, so I believe I do not have to care about that and GOPATH is not set. I do not (for the moment) host my code on GitHub (which is something various articles assume). I have read a number of things, but it all leaves me more confused:
https://golang.org/cmd/go/#hdr-Compile_packages_and_dependencies
https://www.wolfe.id.au/2020/03/10/starting-a-go-project/
https://talks.golang.org/2014/organizeio.slide#1
I have laid out my project according to this: https://github.com/golang-standards/project-layout. (Except this project seems to use a Makefile. I do not want to write a Makefile. I believe this should all work without a Makefile. I really do not want to write a Makefile.)
Here is the structure:
/src
/cmd
main.go
/internal
helper.go
go.mod
go.mod looks like this:
module mycompany/mymodule
go 1.14
service.go looks as follows
package main // this has to be called 'main'
import (
"mycompany/mymodule/internal/helper"
)
func main () {
helper.greet("Jenny")
}
So, if I am in /src and I run build cmd/service.go I get
cmd/service.go:4:2: package mycompany/mymodule/internal/helper is not in GOROOT (/usr/local/Cellar/go/1.14.5/libexec/src/mycompany/mymodule/internal/helper)
Do I have to compile helper.go first? Manually? Surely not. go build surely should be able to build my entire project, right? Including all the dependencies. Could someone please tell me what I am missing?
When you run go build without specifying file path, it will look for the main function inside any .go files at current directory to start. It doesn't build entire project. But it wouldn't be a problem in this case.
You're importing wrong package. The package name to import must be mycompany/mymodule/internal not mycompany/mymodule/internal/helper.
And to invoke a function inside another package, it must be exposed to outside.
So you have to declare the function greet() as Greet()

Go project structure to produce library and cli with the same name in single repository

How to setup project structure to produce library and cli with same name in
single repository?
Suppose my project name is project. I want to make it importable with name
project and have executable binary with name project when installed with
go get. My setup currently is like this:
host.com/project/
project/
main.go
core/
project.go
Then, when installed with:
go get host.com/project/project
it installs project as executable which pulls core as dependency. In
core/project.go file, the package has this:
package project
The problem is it is imported with:
import (
"host.com/project/core"
)
And it exports project as name space not core which violates go's convention.
How can I do this?
This isn't a convention, and you may do however you like, but it's a common practice to have a cmd folder in the project root, and all the executables go under that, each in is own folder.
So a good solution in your case could be simply:
host.com/project/
cmd/
project/
project.go
filea.go
fileb.go
In filea.go and fileb.go the package declaration should be:
package project
In cmd/project/project.go package and import declaration should be:
package main
import "host.com/project"
Of course if your project is more complex, you may create further packages under the project root, and it may have multiple commands (multiple main packages), e.g.:
host.com/project/
cmd/
project/
project.go
prjtool/
prjtool.go
packagex/
x.go
packagey/
y.go
filea.go
fileb.go
An example following this layout is the very popular Go Delve debugger (4.5k stars currently), available at https://github.com/derekparker/delve.
A very complex repository example is the golang.org/x/tools package which is a collection of multiple, essential Go tools, available at https://github.com/golang/tools/. Its cmd folder contains more than 20 subfolders (commands), many of the tools (main packages) even consist of multiple .go files (but each using package main declaration, forming a single package of the executable).
Also check out the following related question: What is a sensible way to layout a Go project

How to import project specific go packages while maintaining a separate location for go packages that are common to totally different projects?

So I was developing a go application for the very first time. I came to know that there are two variables GOROOT and GOPATH which are used to maintain go packages. What I understand till now, is that GOROOT is for the go binary files and GOPATH is mainly for storing library and helper packages that is needed for projects.
Here is my current project structure -
/Users/john/work/project-mars
/Users/john/work/project-mars/main.go
/Users/john/work/project-mars/helper
/Users/john/work/project-mars/helper/helper.go
Content of main.go
package main
import (
"fmt"
"helper"
)
func main(){
fmt.Println("Hello")
}
Content of helper.go
package helper
import (
"fmt"
)
func SayWorld(){
fmt.Println("World")
}
And the go variables are -
GOROOT = /Users/john/apps/go
GOPATH = /Users/john/apps/go-packages
Problem:
Now when I perform the following command, I get this error -
mac-machine:project-mars john$ go build main.go
main.go:5:5: cannot find package "helper" in any of:
/Users/john/apps/go/src/helper (from $GOROOT)
/Users/john/apps/go-packages/src/helper (from $GOPATH)
I understand that GOPATH should be the project directory that I am working on. But I am concerned with keeping my projects and library packages in a modular way, so that when later I have a totally different project (i.e. project-aurora) which might use same github helper packages, that they are not downloaded two times, both in project-mars and project-aurora .
How can I avoid this redundancy while working on different projects ?
Update: It's not that I can not compile them. I can use the GOPATH as my project directory and use src,pkg,bin project layouts and also reorganize the files and finally get to compile the project. yeeeeppi. But my question is about resolving the redundancy of common package problem that appears in this single GOPATH way.
Please read How to Write Go Code carefully. It explains everything you need to know.
You don't use GOPATH as your project directory. Assuming you want to work with the standard Go tooling, your package source needs to be in the directory corresponding to its import path, just like any other package.
Your project should be located at $GOPATH/src/project-mars, which can be built via go install project-mars. The helper package should be located at $GOPATH/src/project-mars/helper, and imported via "project-mars/helper".
Rename your helper-lib folder to helper
Then move this folder from project-mars to the upper folder work
This should make your
import "helper"
statement in main.go work.

"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 do packages with multiple files work in golang?

This repo has 3 go files all begin with "package lumber".
To use this package, I'm supposed to put this in my GOROOT and simply
import lumber
in my program. How do variables and types in this package connect with each other across multiple files? How does the go compiler know which file to begin reading first?
In case I want to read the package, where should I begin reading to understand the package? What exactly is the flow of things here?
To elaborate on jnml's answer:
When you use import "foo/bar" in your code, you are not referring to the source files (which will be located in $GOPATH/src/foo/bar/).
Instead, you are referring to a compiled package file at $GOPATH/pkg/$GOOS_$GOARCH/foo/bar.a. When you build your own code, and the compiler finds that the foo/bar package has not yet been compiled (or is out of date), it will do this for you automatically.
It does this by collating* all the relevant source files in the $GOPATH/src/foo/bar directory and building them into a single bar.a file, which it installs in the pkg directory. Compilation then resumes with your own program.
This process is repeated for all imported packages, and packages imported by those as well, all the way down the dependency chain.
*) How the files are collated, depends on how the file itself is named and what kind of build tags are present inside it.
For a deeper understanding of how this works, refer to the build docs.
No, you're not "supposed to put this in my GOROOT". You're supposed to execute
$ go get github.com/jcelliott/lumber
which will clone the repository into $GOPATH/src/github.com/jcelliott/lumber. Then you can use the package by importing it in your code as
import "github.com/jcelliott/lumber"
About the scoping rules: Declarations and scope

Resources