Go test results in go: cannot find main module, but found .git/config in /Users/dp/Documents - go

Im just getting started with Golang and am trying to run unit tests. When running go test, I end up getting the following output from the terminal
go: cannot find main module, but found .git/config in /Users/dp/Documents
to create a module there, run:
cd ../.. && go mod init
My file structure is fairly simple, as is as follows
├── CARDS
│ ├── .vscode
│ ├── main.go
│ ├── test.go
│ ├── deck_test.go
│ └── my_cards.txt
the contents of deck_test.go are
package main
import "testing"
func TestNewDeck(t *testing.T) {
d := newDeck()
if len(d) != 52 {
t.Errorf("Length is not 52, got %v", len(d))
}
if d[0] != "A of D" {
t.Errorf("First card is not A of D, got %v", d[0])
}
if d[len(d)-1] != "K of C" {
t.Errorf("Last card is not K of C, got %v", d[len(d)-1])
}
}
Any insights would be of help!

Although not required, it's generally advisable to init when you're inside of a Git (or other VCS) repository so that modules can lean on your remotes information to determine the name of the module correctly, for example:
git init
git remote add origin https://github.com/syntaqx/dacode
go mod init
Allows go mod to understand my modules name is likely intended to be github.com/syntaqx/dacode.
Alternatively, and I often do this for sake of not needing to do things in any particular order, you can specify the module name:
go mod init dacode # valid, but..
go mod init github.com/syntaqx/dacode # is generally better, because it describes my remote
By specifying it, modules can just initialize in whatever directory I'm in without having to magic anything from the code.
Note: While you're starting out especially, I highly recommend naming your modules the same naming structure you would use for a repository. By doing so, you're allowing commands like:
go get github.com/syntaqx/dacode
To function correctly without having to do any of the internals yourself. As you learn more about how they work, you can decide if you want to keep that convention or go against the grain, but it's likely more sane to be consistent.
Hope this helped!

I am not using go modules (I know, I should). I got this error after upgrading from older Go versions to 1.16. From release notes:
Note that Go 1.16 requires use of Go modules by default, now that, according to our 2020 Go Developer Survey, 96% of Go developers have made the switch. We recently added official documentation for developing and publishing modules.
To still allow working as before, change it to as it was before. Add this in your .bashrc:
export GO111MODULE=auto

Related

"package XXX is not in GOROOT" when building a Go project

I have a weird issue that arose when I took a break from this project. Upon starting up Goland, I'm riddled with errors when trying to run my project.
The specific error, when building one of my packages, is:
start.go: package project/game is not in GOROOT (C:\Go\src\project\game)
I have a folder structure as such under C:\Users\username
go
|-src
|-project
|-game
|-entity
|-whatever.go
|-game_stuff.go
|-server
and my env vars are as such:
GOROOT=C:\Go
GOPATH=C:\Users\ketchup\go
for each of the modules (project/game/entity, project/game, project/server), I did a git mod init.
When building, Goland will try to run this:
C:\Go\bin\go.exe build -o C:\Users\ketchup\AppData\Local\Temp\___go_build_project_server.exe project/server
and return the error.
Can anyone help me with this issue? Kind of lost since Goland was working fine the last time I opened it. Also not even sure what direction to look at - I'm pretty new to Go and I'm not really sure what documentation to look at :\ Thank you everyone!
In newer versions (post 1.13) of Go, you don't need to set environment variables like GOPATH, GOBIN, etc.
You also need to have a go.mod file at the project root. This will make the directory a Go module. This is also where the .git/ is located. This means that only one go.mod is needed per repository. Inside the project root you could do a go mod init remote-repo.com/username/repository
I installed Go using Homebrew on macOS so GOROOT is /opt/homebrew/Cellar/go/1.17.5/libexec. This location contains the standard library and runtimes for Go.
test and run commands are run in the format go COMMAND package_path/xxx. Without specifying the package_path ./ and just running go COMMAND xxx, the compiler assumes that the module xxx is located in GOROOT, and throws error package xxx is not in GOROOT (path/to/GOROOT/src/xxx) because it doesn't exist.
This behavior is expected because the package we are working with is not part of the Go SDK, i.e., not in GOROOT. The package we are working with will either end up in the go workspace or in the current working directory. Running go install compiles and puts an executable binary in $GOBIN (a.k.a $GOPATH/bin - here $GOPATH is the Go workspace). Running go build from inside a package compiles and puts an execuatble in that directory.
You haven't listed the files inside the server/ package and which file has the main function, so I'll emulate 3 workflows of a calculator each demonstrating more complexity. The last workflow is similar to your directory structure.
Directory Structure
Version 1:
Getting started with packages
Basic functionality
calculatorv1
├── go.mod <- go mod init github.com/yourname/calculatorv1
└── basic/
├── add.go
├── add_test.go
├── main.go
├── multiply.go
└── multiply_test.go
Version 2:
More functionality
Multiple packages
calculatorv2
├── go.mod <- go mod init github.com/yourname/calculatorv2
├── main.go
└── basic/
│ ├── add.go
│ ├── add_test.go
│ ├── multiply.go
│ └── multiply_test.go
└─── advanced/
├── square.go
└── square_test.go
Version 3:
Even more functionality
Nested packages
calculatorv3
├── go.mod <- go mod init github.com/yourname/calculatorv3
├── main.go
└── basic/
│ ├── add.go
│ ├── add_test.go
│ ├── multiply.go
│ └── multiply_test.go
└─── advanced/
├── square.go
├── square_test.go
└── scientific/
├── declog.go
└── declog_test.go
Workflow
Note: Substitute xxx with basic, advanced, or advanced/scientific depending on the version you're working with.
Initialize Go module in the project directory (one of calculatorv1, calculatorv2, or calculatorv3) using go mod init
Run tests
go test -v ./... (from the project root, recursively execute all test suites)
OR
go test -v ./xxx (from the project root, run the test suite in package "xxx")
OR
cd xxx/
go test -v # (from inside the package)
Compile and execute package
go run ./... (from the project root, recursively run all .go files except tests)
OR
go run ./xxx (from the project root, run all .go files in "xxx" package except tests)
OR
cd xxx
go run . # (from inside the package)
NOTE: Only files in the main package are executable, i.e., files having declaration package main. This means that go run ./xxx will only work with version1, and not versions 2 and 3. So instead for versions 2 and 3, run go run main.go
Code
Very easy to fill in incomplete bits
Version 1
add.go
package main
func addition(x int, y int) int {
return x + y
}
add_test.go
package main
import "testing"
func TestAdd(t *testing.T) {
t.Run("adding two positive numbers", func(t *testing.T) {
sum := addition(2, 2)
expected := 4
if sum != expected {
t.Errorf("Expected %d; but got %d", expected, sum)
}
})
t.Run("adding two negative numbers", func(t *testing.T) {
sum := addition(-3, -4)
expected := -7
if sum != expected {
t.Errorf("Expected %d; but got %d", expected, sum)
}
})
t.Run("adding one positive and one negative integer", func(t *testing.T) {
sum := addition(1, -3)
expected := -2
if sum != expected {
t.Errorf("Expected %d; but got %d", expected, sum)
}
})
}
main.go
package main
import "fmt"
func main() {
var num1 int = 1
var num2 int = 2
sum := addition(num1, num2)
product := multiplication(num1, num2)
fmt.Printf("The sum of %d and %d is %d\n", num1, num2, sum)
fmt.Printf("The multiplication of %d and %d is %d\n", num1, num2, product)
}
Version 2
main.go
package main
import (
"fmt"
"github.com/yourname/calculatorv2/basic"
"github.com/yourname/calculatorv2/advanced"
)
func main() {
var num1 int = 1
var num2 int = 2
product := basic.Multiplication(num1, num2)
square := advanced.Square(num2)
fmt.Printf("The product of %d and %d is %d\n", num1, num2, product)
fmt.Printf("The square of %d is %d\n", num2, square)
}
multiply.go
package basic
func Multiplication(x int, y int) int {
return x * y
}
multiply_test.go
package basic
import "testing"
func TestMultiply(t *testing.T) {
t.Run("multiplying two positive numbers", func(t *testing.T) {
sum := Multiplication(2, 2)
expected := 4
if sum != expected {
t.Errorf("Expected %d; but got %d", expected, sum)
}
})
t.Run("multiplying two negative numbers", func(t *testing.T) {
sum := Multiplication(-3, -4)
expected := 12
if sum != expected {
t.Errorf("Expected %d; but got %d", expected, sum)
}
})
t.Run("multiplying one positive and one negative integer", func(t *testing.T) {
sum := Multiplication(1, -3)
expected := -3
if sum != expected {
t.Errorf("Expected %d; but got %d", expected, sum)
}
})
}
square.go
package advanced
func Square(x int) int {
return x * x
}
Version 3
main.go
package main
import (
"fmt"
"github.com/yourname/calculatorv3/basic"
"github.com/yourname/calculatorv3/advanced"
"github.com/yourname/calculatorv3/advanced/scientific"
)
func main() {
var num1 int = 1
var num2 int = 2
var num3 float64 = 2
product := basic.Multiplication(num1, num2)
square := advanced.Square(num2)
decimallog := scientific.DecimalLog(num3)
fmt.Printf("The product of %d and %d is %d\n", num1, num2, product)
fmt.Printf("The square of %d is %d\n", num2, square)
fmt.Printf("The decimal log (base 10) of %f is %f\n", num3, decimallog)
}
square.go
package advanced
func Square(x int) int {
return x * x
}
declog.go
package scientific
import "math"
func DecimalLog(x float64) float64 {
return math.Log10(x)
}
declog_test.go
package scientific
import "testing"
func TestDecimalLog(t *testing.T) {
t.Run("adding two positive numbers", func(t *testing.T) {
sum := DecimalLog(100)
expected := 2.0
if sum != expected {
t.Errorf("Expected %f; but got %f", expected, sum)
}
})
t.Run("adding two negative numbers", func(t *testing.T) {
sum := DecimalLog(10)
expected := 1.0
if sum != expected {
t.Errorf("Expected %f; but got %f", expected, sum)
}
})
}
You may have GO111MODULE set "on", which will be on the go mod. Turning off the GO111MODULE may resolve this problem.
go env -w GO111MODULE=off
A pretty dumb conclusion (mostly on my part) but my issue came from having done go mod init in each of the folders. after removing go.mod and go.dep from each of the folders I did go mod init in, I could build without issue (through terminal)
Also, my packages in GoLand were not being detected because I had Go Modules enabled in the Settings. I disabled it and GoLand was able to index the external packages and my own packages.
To anyone who does want modules to work with GoLand after they have stopped doing so, make sure 'Enable Go modules integration' is checked in the Preferences as such:
So it looks like if you running go mod init 'xxx' the xxx is core name of your project. In there main packages complete name is 'xxx/main' so if you have your project root folder like this:
root -> go mod init xxx
|- main.go -> package "main"
|- tools
|- helper.go -> package "tools"
and you want to import tools package from main.go you need to import this "xxx/tools"
I made the mistake of changing the module name inside go.mod file manually. After fixing it, it worked fine.
└── hello
├── go.mod
├── go.sum
├── hello.go
└── morestrings
├── reverse.go
└── reverse_test.go
Excerpts of hello.go
import (
...
"hello/morestrings"
...
)
Running go build in hello directory was giving following error:
hello.go:5:2: package hello/morestrings is not in GOROOT (/usr/local/go/src/hello/morestrings)
While running command go mod init you need to add folder name, not main.go page name.
Like: go mod init confirm_enrl. confirm_enrl is project folder name
I met the same error with the project layout
project
|- pgk
|- src
|-module1
|- some.go
|- main.go
some.go
package module1
...
main.go
import "project/module1"
Originally, I import module1 through ./module1, the error package module1 is not in GOROOT comes up. I solve it through import "project/module1".
PS: per golang project layout, src should NOT in golang project.
I got the same error when I had a spelling mistake in the package name. Therefore, it might be the root cause behind this error. Maybe it will be useful for someone.
For me it was because my main method wasn't inside package main
package main
func main() {
{
}
For my case just updating my go version to the latest solved the issue .
I downloaded the latest binary and installed it and boom all was sorted !
In my case, it is cause by changing goroot path.
GOROOT is a variable that defines where your Go SDK is located
it will work if you change you goroot to where go sdk you installed
It seems a little funny, but I faced same error because of running:
go run build
instead of
go build main.go
So it shows that everything after build or run should have a recognized path by go.
Had this problem, deleted my go.mod & go.sum files then rebuilt it using
go mod init
This solved my problem :)
Windows PC user
For me the issue was in how I was attempting to run the project
While at the root folder of the project and my main.go file is in /cmd/web/
I faced the issue when I tried to run both
go run cmd/web/.
go run /cmd/web/.
It only worked when I used the
go run ./cmd/web/.
Notice the . at the start
In my own case, it turned out that I was using go run main instead of go run main.go
I came across the same like issue when i was following go getting started tutorial with goland default awesomeProject.
What i did after crating project run this command go mod init example.com/hello but my root directory name was different than example.com/hello.
After manually edit the go.mod file and replace awesomeProject with example.com/hello the build works successfully.
I knew this is about one year ago. I just want to share same experience for those who have, have modules in local folders..
The problem is because you have not publish your module to a central location like github.
You have to run this command to tell go that the module is a local module
go mod edit --replace external_folder_module_name= ../pathItsLocated
I was also faced similar error while building the docker image. The error was #19 0.785 controllers/vasaprovider_controller.go:28:2: package vasa-operator/config/configs is not in GOROOT.
After adding the go file location in Dockerfile, it worked for me. The lines I had added are:
COPY config/configs config/configs/
COPY --from=builder /workspace/config/configs config/configs/
In my case, I was trying to build from the wrong directory. The old directory didn't even have any .go files.
Make sure your import statement matches the module name that you defined in your go mod.
just initialise the project with mod file and start working on on root folder.
go mod init <name-anything>
We can solve this problem by writing this command on terminal: go env -w GO111MODULE=off
But after this command, you will be not able to use go mod init through terminal. You must create "go.mod" file manually.
I don't like that everyone is giving an answer which uses github module naming conventions as if you have to name them in that way or to have your module on github for it to be used within a local environment, so here's my answer to — hopefully — help clarify a few moments I was confused about regarding the naming of packages and modules in Go (I will use deliberately unusual names for the files and folders so you could see that you don't have to name your files a specific way for your Go project to work (you have to structure them in a specific way though)):
So, Golang project conceptually has:
(this is optional for a Go project)
"Repository" — a place in a version control system where the source code for a project is stored (usually some remote repo).
(this is required for a Go project to compile)
"Module" — this name, conceptually, in a Go project, is used to specify the program/library as a whole (meaning, it refers to its root, which is usually stored in some remote repository).
"Packages" — in a Go project, this name is applied to literal folders within which the "package files" are stored — It's a way of organizing code within a module.
In practice, the concepts from above imply that if you want to create a multi-package project, for it to compile, you need to do the following:
(step-by-step example:)
-- Create a folder that will serve as a root folder for the project and cd into it:
$ mkdir some_amazing_project && cd some_amazing_project
-- A collection of Go code becomes a module when there's a valid go.mod file in its root directory, so use the following command to generate it:
$ go mod init my_amazing_module_lib_program
(The inside of your go.mod file looks like this):
module my_amazing_module_lib_program // this is your unique module identifier and you use this name as a relative root for your package names when you use "import"
go 1.19
-- Now create an entry point to your Go program which is a go file that should be placed in the root folder (where the go.mod file resides), but you could just as well place it in any subfolder within this module (the root folder), but no deeper than that (or you'll receive the "no Go files in <absolute_path>/some_amazing_project/some_subfolder/another_folder" error):
$ touch some_main_file.go
(^^ you can call this file whatever you want, but the convention is "main.go")
-- Inside of that main file you must specify the package to be main and you must have a function within that file that is also called main:
// some_main_file.go
package main
import "fmt"
func main() {
fmt.Println("hello there")
}
(This is your project structure so far):
some_amazing_project/
|- go.mod
|- some_main_file.go
(Now, let's say you want to create a package within this module/program/library. You would need to do the following):
-- Create a new folder, call it "amazing_package" and create any .go file in it (the name of the file doesn't really matter as only the name of the containing folder is used to refer to the package from other .go files):
$ mkdir amazing_package && cd amazing_package && touch whatever_file.go
-- Inside of the whatever_file.go you use the package keyword to specify the name of this package (this package name will be used only when specifying the name of the function to invoke from within other .go files — you'll see in a bit):
// whatever_file.go
package wowow
import "fmt"
func PrintWowow() {
fmt.Println("this is from wowow package")
}
^^ The variables/constants/functions/types/etc..(any "identifier" in Go) that starts with an uppercase letter is exported and is made available to be imported into other packages.
(For the sake of example, let's create another file inside of this package):
$ touch another_cool_file.go
-- Inside of the another_cool_file.go you use the same package keyword to specify the name of this package as you've used for in the whatever_file.go (because these files are in the same "package" conceptually, meaning that in practice they are stored in the same folder (if you use a different name for the package keyword while storing the file in the same folder, you'll receive an error during compilation)):
// another_cool_file.go
package wowow
import "fmt"
var Some_var = 42 // this will also be automatically exported
func PrintAnotherWow() {
fmt.Println("this is also from wowow package, but from a different file")
}
(This is your project structure so far):
some_amazing_project/
|- go.mod
|- some_main_file.go
|- amazing_package/
|- whatever_file.go
|- another_cool_file.go
-- Now, to reference the "PrintWowow" and "PrintAnotherWow" function from ANY other .go file within this entire module you use the unique module identifier from go.mod file and a path relative to that identifier that specifies the location of a package folder to import (I'll use the some_main_file.go in this example. We re-write it like so):
// some_main_file.go
package main
import (
"fmt"
"my_amazing_module_lib_program/amazing_package"
)
func main() {
fmt.Println("hello there")
// now you use the name of the package specified inside of those files from *amazing_package* folder
wowow.PrintWowow()
wowow.PrintAnotherWow()
fmt.Println("and this is Some_var from the same imported package:", wowow.Some_var)
}
And here is the result of running go build . && go run . while inside of my_amazing_module_lib_program (root) folder:
hello there
this is from wowow package
this is also from wowow package, but from a different file
and this is Some_var from the same imported package: 42
if you are getting package project/game is not in GOROOT (C:\Go\src\project\game), and you have a go.mod file... have you checked the imports in my *.go files to confirm they are synching up properly. If not then perhaps you should start there.
I get this error every once in a while especially when I am setting up a new project. first thing I do is confirm my imports and that usually fixes everything. thank you goland ;)
in my case the handler path in serverless.yaml for the function in functions was incorrect

How to structure multi language repository to work reasonably with golang?

I want to make a library with few language bindings, one of them being golang. It would make sense to have it all in one repository, because for example test data can be shared between them. But I'm not sure how to structure it. I've tried is
+ $ tree .
.
└── go
├── go.mod
└── foo.go
1 directory, 2 files
+ $ cat go/go.mod
module github.com/bar/foo/go
go 1.13
+ $ cat go/foo.go
package foo
func Foo() int {
return 1;
}
Then I tried to use it
+:( $ cat test.go
package main
import (
"github.com/bar/foo/go"
)
func main() {
fmt.Println(foo.Foo())
}
But it failed with
+ $ go run ./test.go
go: finding github.com/bar/foo latest
build command-line-arguments: cannot load github.com/bar/foo/go: module github.com/bar/foo#latest (v0.0.0-20191019071519-05aedbdfa600) found, but does not contain package github.com/bar/foo/go
I'm fairly new to golang, so could someone please advice on how are projects like this usually structured?
First of all, in most cases it is a bad idea to name a package after the programming language. What does the package actually DO? Remember, documentation and package layout should be optimized for the user.
For multi-part projects, I personally tend to set up a new organization say foo and create a bar repo for the first part, say the server written in Java, which then would be accessible via https://github.com/foo/bar. Next, for the client written in Go, you set up the next repo baz, which then would be accessible via https://github.com/foo/baz - your go module.
Last, but not least, you can have a „distribution“ repository, which puts the organization‘s projects through a CI pipeline to ensure interoperability.
This approach has multiple advantages, imho: You make it easier for the user to explore the ecosystem, the repos become sufficiently independent while still being tied together by the organization and the individual repos become smaller.

Are there conventions for Go module names in mono-repos with multiple modules?

In a multi-module repository, should a module name (set via the go.mod module directive) follow the conventions of package naming?
E.g. module github.com/org-name/repo-name/path/to/module-dir
I understand that, whatever the module is named, the packages within the module refer to each other using the module name as prefix. But, from outside the module, there seems to problems if the module name is set to something other than the <host><path-within-repo> pattern. get-ing a package included in the module then gives messages about unrecognized import path.
Is there any cause to name a module differently than <host><path-within-repo> ?
There isn't any hard requirement for referencing modules, although it always good practice to use the domain/repo pattern. So, if you want to reference other modules locally that are not in the GOPATH, you can use the replace directive.
https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive
replace also can be used to inform the go tooling of the relative or absolute on->disk location of modules in a multi-module project, such as:
replace example.com/project/foo => ../foo
Let's say we have the following structure:
├── .gitignore
├── pkg1
│   ├── go.mod
│   └── main.go
└── pkg2
├── go.mod
└── utils.go
pkg1/main.go
package main
import (
"fmt"
"local/pkg2"
)
func main() {
fmt.Println(pkg2.Add(1, 2))
}
pkg1/go.mod
module local/pkg1
go 1.12
require local/pkg2 v0.0.0
replace local/pkg2 => ../pkg2
pkg2/utils.go
package pkg2
func Add(a, b int) int {
return a + b
}
pkg2/go.mod
module local/pkg2
go 1.12
Running:
cd pkg1
go run main.go
You get:
3
If you want to be able to go get a module, it should follow the <host>/repo/path/within/repo pattern.
However, I would suggest stepping back and asking if you really do want a multi-module repo. It adds substantial complexity, it is hard to get right, and usually means more work on an on-going basis.
Russ Cox commented in #26664:
For all but power users, you probably want to adopt the usual convention that one repo = one module. It's important for long-term evolution of code storage options that a repo can contain multiple modules, but it's almost certainly not something you want to do by default.
For more details, see "Organize local code in packages using Go modules".

go mod: cannot find module providing package

I am creating a go project with version 1.12.1.
If I run GOPATH="$(pwd)/vendor:$(pwd)" GOBIN="$(pwd)/bin" go clean I get the following error:
can't load package: package github.com/marvincaspar/go-example: unknown import path "github.com/marvincaspar/go-example": cannot find module providing package github.com/marvincaspar/go-example
This is only for go clean, go run or go build works fine.
Here is the folder structure of main code:
.
├── Makefile
├── cmd
│ └── server
│ └── main.go
├── go.mod
├── go.sum
└── pkg
└── storage
└── mysql
└── storage.go
Here is how the go.mod file looks like:
module github.com/marvincaspar/go-example
go 1.12
require (
github.com/go-sql-driver/mysql v1.4.1
)
And finally the main.go file:
package main
import (
"fmt"
"os"
"github.com/marvincaspar/go-example/pkg/storage/mysql"
)
func main() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
}
func run() error {
// init storage
s := mysql.NewStorage()
// do some other stuff...
}
Any ideas what I am doing wrong?
I generally use go get and go mod tidy for same. It works all the time.
go mod tidy
Normally this new project approach works for me:
go mod init <project_name>
go test
I have found that developing projects outside of GOROOT and GOPATH are much easier
Go build/install is trying to find main package in your root directory, it is not checking sub-directories (cmd/server) in your case. Hence you are getting package not found error.
To properly build your code, you can run:
go build github.com/marvincaspar/go-example/cmd/server
Similarly, to run your project, you will have to provide module-name/main-package-path:
go run github.com/marvincaspar/go-example/cmd/server
Go clean can be executed in same way, by providing module-name/path-with-main-package
go clean github.com/marvincaspar/go-example/cmd/server
or
GOPATH="$(pwd)/vendor:$(pwd)" GOBIN="$(pwd)/bin" go clean github.com/marvincaspar/go-example/cmd/server
However, as per https://blog.learngoprogramming.com/code-organization-tips-with-packages-d30de0d11f46, just put your source files into your project’s root. It’s better that way.
This can also happen if you are using workspaces. It seems like you can't use one package without workspaces if you are using others with workspaces.
So try going into your top level workspace and do
go work use ./problemPackage.
At least this worked for me.
To solve this problem you have to do few things, First, go to the project directory via the Terminal then run the following command ( If you are using git clone then go to the clone directory folder via Terminal and run the following command):
Step 1: sudo go mod init your-program.go
Step 2: sudo go mod tidy
Step 3: sudo go build your-program.go

How can I resolve dependencies in nested application binary in Go project?

This sounds stupid, but I am trying for build my new golang project for a while now and I am stuck with following error
can't load package: package github.com/kuskmen/yamq/cmd/yamq-client: found packages main (main.go) and yamqclient (yamq-client.go) in C:\projects\yamq\cmd\yamq-client
I know this should be straightforward to fix, but I come from .NET and I am still not experienced in Go projects and its dependency resolution model hence the struggle.
My project structure looks like so
/yamq
/cmd
/yamq-client // yamq client application binary
main.go // package main
yamq-client.go // package yamqclient
/yamq-server // yamq server application binary
main.go // package main
yamq-server.go // package yamqserver
go.mod // contains only "module github.com/kuskmen/yamq" for now
... // some library files that will probably be moved to /shared folder
so far so good, when I do go build in outermost directory ( /yamq ) it is building successfully (or at least it is not showing any errors), but when I try to build either yamq-client or yamq-server binaries I get the aforementioned error and every time I try to google it or find something useful I got some old article or answer that dates back 2013-2016 that suggests something about $GOPATH and etc which shouldn't be the case here since I am trying to use go modules.
Help a fellow .NET developer join Go community by explaining him how exactly modules work cause I found this and this useless or at least I am missing the point, thanks in advance!
To follow up from my comment above:
From https://golang.org/doc/code.html:
Go programmers typically keep all their Go code in a single workspace.
A workspace contains many version control repositories (managed by Git, for example).
Each repository contains one or more packages.
Each package consists of one or more Go source files in a single directory.
The path to a package's directory determines its import path.
For your project, I'd do something like this:
$ tree
.
├── clientlib
│   └── lib.go
├── cmd
│   ├── client
│   │   └── main.go
│   └── server
│   └── main.go
├── go.mod
└── serverlib
└── lib.go
5 directories, 5 files
$ cat go.mod
module myproject.com
The module name is arbitrary (could be github.com/yourname/yourproject).
For the server side:
$ cat serverlib/lib.go
package serverlib
import "fmt"
func Hello() {
fmt.Println("Hello from serverlib.Hello")
}
$ cat cmd/server/main.go
package main
import (
"fmt"
"myproject.com/serverlib"
)
func main() {
fmt.Println("Running server")
serverlib.Hello()
}
And now we can build and run it:
$ go build -o server cmd/server/main.go
$ ./server
Running server
Hello from serverlib.Hello
The client side looks symmetrical.
Variations: you could name the .go files in cmd/... by their actual binary names - like server.go and client.go. The package in each is still main, but then go build creates an executable with the file's name (sans the .go) without needing to -o explicitly.

Resources