How to run sibling Go applications (modules) from the parent directory - go

I have multiple Go projects (and all of them are also Go modules) all in a folder. They are all HTTP servers and exchanging REST calls, thus, I need all of them up and running simultaneously.
So, for local testing purposes, I thought it would be reasonable to run all of them from the parent instead of moving all of the project root directories and running go run main.go in multiple terminals.
container_dir/
├── prj1/
│ ├── go.mod
│ ├── main.go
│ └── ...
├── prj2/
│ ├── go.mod
│ ├── main.go
│ └── ...
└── ...
Here are some some commands I have tried and the error messages for each time:
container_dir $ go run ./*/*.go
##ERROR: named files must all be in one directory; have ./prj1/ and ./prj2/
container_dir $ go run *.go
##ERROR: stat *.go: no such file or directory
container_dir $ go run ./prj1 ./prj2/
##ERROR: cannot find package "github.com/jackc/pgx/v4" in any of:
/usr/local/go/src/github.com/jackc/pgx/v4 (from $GOROOT)
/home/user/go/src/github.com/jackc/pgx/v4 (from $GOPATH)
cannot find package ...
So, I can give a final rephase for the question: How to run multiple go modules in sibling directories when they have some third party dependencies etc.?
P.S: As possible with Go modules suggest container_dir for my projects is in an arbitrary location and I expect no $GOPATH relevance.
Go version: 1.13.6

Don't use go run outside of tiny, playground-style tests
Source paths are a compile-time concern and are irrelevant at runtime - being in "sibling directories" doesn't mean anything when the program is running
go run runs a single program; just like building a program and running its executable binary (which is what go run does) runs a single program.

Looks like your go.mod stuff is having problems dude.
remember you can do replace inside it and reference your other application
module container_dir/prj2
go 1.13
require(
container_dir/prj1 v0.0.0
)
replace (
container_dir/prj1 => ../prj1
)
require is the path you import but it'll get switched to the relative path on build.

Related

How to fix Go build error "can't load package" with Go modules?

I'm setting up a new project using Go modules with this tutorial, and then trying to build it.
The module is located in a folder outside of the $GOPATH with the following structure:
example.com
├── my-project
├── ├── main
├── ├── ├── main.go
├── ├── go.mod
I've run go mod init example.com/my-project in directory example.com/my-project and created the go.mod file shown above.
main.go has basic contents:
package main
import (
"fmt"
)
func main(){
fmt.Println("Hello, world!")
}
After attempting to run go build in directory example.com/my-project, I receive the following error message:
can't load package: package example.com/my-project: unknown import path "example.com/my-project": cannot find module providing package example.com/my-project.
I've also attempted to run go build in directory /, outside of example.com/my-project, and I get similar, failing results:
can't load package: package .: no Go files in ...
I'm probably getting some basic thing wrong, so thanks for your patience and any help you can give.
no need for the directory main,
just move your main.go and go.mod to example.com/my-project and it will work.
Project root should look like:
.
├── go.mod
└── main.go
In my case it was that the variables GOMOD and GOWORK were taking other values different from the project I solved it by executing the command go env and verifying the values of those variables and deleting the files of that address.
Then I removed the go.mod and go.sum file from the project and ran the following commands again:
go mod init projectName
go mod tidy
go run ./...
And it worked perfectly.

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.

Structuring a multi-executable Go project

I am trying to build a micro-services architecture project in Go. I am currently using Go 1.11 which supports modules, so I put my root directory in an arbitrary chosen directory, outside of GOPATH.
If I am getting the micro-services architecture concepts right, although my microservices need to be independent, they can share dependencies (and I don't see another way to do stuff, is it?)
Below is my directory structure:
.
├── go.mod
├── lambda
│   └── account_create
│   └── main.go
├── readme.md
└── types
├── account.go
├── location.go
├── order.go
├── pricing.go
├── product.go
└── types.go
Now the behavior I expected was to be able to run go build lambda/account_create and get an executable with that functionality so I can supply it to the respective AWS Lambda function.
However, when I run the command, I get:
can't load package: package lambda/account_create: unknown import path "lambda/account_create": cannot find module providing package lambda/account_create
Please explain me why this does not work and give me some advice on how a project like this should look.
Thank you very much!
Edit Here is my lambda/account_create/main.go file contents:
package account_create
import (
"fmt"
"roasted.ro/pkg/types"
)
func main() {
account := types.UserAccount{Name: "Victor"}
fmt.Printf("Welcome %s", account.Name)
}
To answer the latter part of your question (as the first half is more about preference), you need to do:
go build ./lambda/account_create
Notice the ./. go build takes in a package name or a path. If you don't prepend the path with a ./, it assumes you are giving it a package name.
Edit: the package has to be main if you want an executable. According to the docs, you always have to use package main for projects that build an executable:
Executable commands must always use package main.
Edit: I'll add some opinions on layout:
Consider which parts of your project are exported to other go projects. Meaning someone could import your package and expect to gain value and not have their code break when yours changes.
That should be either in a github.com/you/pkg/somepath package or just github.com/you/somepath.
Anything else (other than main packages) should be under a /internal package.
I typically make a /cmd/myexecurable1 /cmd/myexecurable2 and so forth for each executable.

Where to place go.mod file

I have a repository structure as follows :-
xyz/src
1. abc
- p
- q
- r
2. def
- t
- u
- v
3. etc
- o
- m
- n
I have created a .mod file in src and run go build ./...
Except for local packages everything is fine. So if abc/p is being used in def then it throws the following exception :- cannot find module providing package abc/p. The idea behind keeping the .mod file in src package was to make sure the path is being found from where the mod file is located. Can anyone suggest where should the mod file ideally should be? also i tried placing it one directory above in xyz but still same issue as well as i created one for each sub directory. I am bit confused on this. Will I have to create separate repository for abc and etc. But considering gopath which earlier used to work for the same I think module should also be able to do the same. Any suggestions?
The most common and easiest approach is a single go.mod file in your repository, where that single go.mod file is placed in the root of your repository.
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.
The Modules wiki says:
For example, if you are creating a module for a repository
github.com/my/repo that will contain two packages with import paths
github.com/my/repo/foo and github.com/my/repo/bar, then the first
line in your go.mod file typically would declare your module path as
module github.com/my/repo, and the corresponding on-disk structure
could be:
repo/
├── go.mod <<<<< Note go.mod is located in repo root
├── bar
│   └── bar.go
└── foo
└── foo.go
In Go source code, packages are imported using the full path including
the module path. For example, if a module declared its identity in its
go.mod as module github.com/my/repo, a consumer could do:
import "example.com/my/repo/bar"
That imports package bar from the module github.com/my/repo.
I have a single go.mod in the root of my go application. I am using the following structure inspired by Kat Zien - How Do You Structure Your Go Apps
At the minute one of my applications looks like this
.
├── bin
├── cmd
│   ├── cli
│   └── server
│ └── main.go
├── pkg
│   ├── http
│   │   └── rest
| │ # app-specific directories excluded
│   └── storage
│   └── sqlite
All packages are imported via their full path, i.e. import "github.com/myusername/myapp/pkg/http/rest" otherwise it causes problems all over the place and this was the one change I had to make going from $GOPATH to go mod.
go mod then handles all the dependencies it discovers properly as far as I've discovered so far.

Go project with 2 executables

Hi all I am fairly new to Golang, I am writing a toy client and server app just to learn the libraries.
But I have the project folder:
philipherron#Philips-iMac {~/workspace/gospace/src/github.com/redbrain/station} $ echo $GOPATH
/Users/philipherron/workspace/gospace
I wanted to have 2 binaries:
client.go
server.go
But when I build I get:
philipherron#Philips-iMac {~/workspace/gospace/src/github.com/redbrain/station} $ go build github.com/redbrain/station/
# github.com/redbrain/station
./server.go:5: main redeclared in this block
previous declaration at ./client.go:5
I guess this is because it looks like I am making to mains in the same package.
So I tried creating a client and a server subdir and have the binaries in each of those, but I get:
philipherron#Philips-iMac {~/workspace/gospace/src/github.com/redbrain/station} $ go build github.com/redbrain/station/client
go install github.com/redbrain/station/client: build output "client" already exists and is a directory
I guess this is because I have the layout of:
$ tree
.
├── client
│   └── client.go
└── server
└── server.go
2 directories, 4 files
Not sure how to get around this, it would just be nice to have the same client and server in the same directory but maybe this is against how I should be doing things in go?
just rename your .go files. The compiler is trying to write to 'client' but 'client' is already taken by the directory.
$ tree
.
├── client
│ └── main.go
└── server
└── main.go
2 directories, 4 files
And/Or create a script that outputs them with a different name go build -o client client/main.go
along with with separate packages as above, if you set the GOBIN=$GOPATH/bin then it will create client and server in the bin dir and it will not collide with dir names

Resources