How can I work with multiple Go projects locally? - go

I'm working on multiple projects in go using modules.
Project 1: github.com/company/project1
/
- /auth
- service.go
- main.go
- go.mod
Project 2: github.com/company/project2
/
- /cart
- service.go
- main.go
- go.mod
If I have in my project2/go.mod next import: github.com/company/project1 and I already created both projects on Github.
How can I test both projects locally? I mean, without pushing test code (on project1) and using go get github.com/company/project1 previously because I just want to push my last commits when I finish both codes (project1 and project2).

As #CeriseLimón and #oakad pointed out in their comments, using replace in your go.mod files allow to use local copies of a repo instead of requiring to commit the project that is a dependency.
Project 2's go.mod:
module github.com/company/project2
require (
...
github.com/company/project1 v0.0.0
)
replace github.com/company/project1 => LOCAL_PATH
Replace LOCAL_PATH for your relative path from project2 to project1, for example, if both are find under $GOPATH/src, LOCAL_PATH would have to be replaced by ../project1 (considering that the project1 directory is named project1). You should also replace v0.0.0 to another version if it applies (this is, if project1 has different versions, the line inside the requirte block should point to the right version. The ellipsis (...) represents any other dependency of your project2.
NOTE: you should not push the replace github.com/company/project1 => LOCAL_PATH line to your VCS unless every developer uses the same relative path and you have some sort of automated or manual way of removing that line before releases, as you do not want that line to be present in releases.

Related

How do I import generated SDKs in golang?

I've used openapi-generator to generate multiple SDK separately and put it in the same parent dir:
sdks
--- bar-api
------ go.mod
--- foo-api
------ go.mod
I'd like to be able to import bar-api in my client code. Initially there's bar-api's go.mod was generated as:
module github.com/coolrepo/bar-api
go 1.13
but I couldn't fix the imports in my client code:
bar "github.com/cool-repo/bar-api"
so what I did was:
sdks
--- bar-api
------ go.mod
---go.mod
i.e., created sdks/go.mod:
module github.com/coolrepo
go 1.13
and manually edited bar-api's go.mod to:
module github.com/coolrepo/bar-api
require (
...
)
replace github.com/coolrepo => ./..
go 1.15
Is there a better way to fix it? This one seems to work but looks kinda hacky with this replace.
The “better way to fix it” is to put all of the generated Go packages inside a single module, instead of splitting up the repo into multiple modules.
rm bar-api/go.mod
go mod tidy
You only really need to split a repo into separate modules if you need to be able to tag a release for one set of packages independently from another set of packages in the same repo. For generated service APIs, that probably isn't worth the development overhead of juggling versions for multiple modules.

How to import a local package from different directory in Go Modules?

I have a project which includes 6 microservices. Every microservices are in its own directory and they are Go modules, like:
- user-ms
- project-ms
- messages-ms
There are some duplicated codes in all microservices, like mongo methods, some configs, and some structs etc. I want to merge all the duplicated codes into a package. Then, I am willing to import the package on our microservices. Creating a repository on Github is impossible for me due to company restrictions.
If I create a folder in $GOPATH/src/, I don't know how to include it on docker-compose.yml.
Is it possible to create a folder ("common-utils") then import on the other modules?
- user-ms
-- go.mod
- project-ms
-- go.mod
- messages-ms
-- go.mod
- common-utils
-- go.mod
You can replace your package name with local package.
go mod edit -replace github.com/remote_package=../local_package
go mod tidy

Can a go module have no go.mod file?

I ran into a repo that seems to be a Go module, but there's no go.mod file in it: github.com/confluentinc/confluent-kafka-go.
Is it ok for a go module to have no go.mod file with dependencies, or the authors of that library just didn't migrate to modules yet?
Dependency modules do not need to have explicit go.mod files.
The “main module” in module mode — that is, the module containing the working directory for the go command — must have a go.mod file, so that the go command can figure out the import paths for the packages within that module (based on its module path), and so that it has a place to record its dependencies once resolved.
In addition, any modules slotted in using replace directives must have go.mod files (in order to reduce confusion due to typos or other errors in replacement paths).
However, in general a module that lacks an explicit go.mod file is valid and fine to use. Its effective module path is the path by which it was required, which can be a bit confusing if the same repository ends up in use via multiple paths. Since a module with no go.mod file necessarily doesn't specify its own dependencies, consumers of that module will have to fill in those dependencies themselves (go mod tidy will mark them as // indirect in the consumer's go.mod file).
SHORT SUMMARY OF THE DISCUSSION:
The answer is "No"!
This project contains a set of go packages, but it is not a Go module as it doesn't contain go.mod file (although, it used to be a multi-module repo (Go) previously).
go get can run in both ways: module-aware mode and legacy GOPATH mode (as of Go 1.16).
To read more about this, refer to docs by using the go command:
$ go help gopath-get
and
$ go help module-get
It'd tell about how go get works in both cases.
Also, I noticed that it can download any repository and would treat it as a Go package, even if it contains an arbitrary Python project.
I did a simple test to demonstrate the same:
$ go get github.com/mongoengine/mongoengine
And it surprisingly worked.
Modules are defined by their go.mod file. Without a go.mod file, it is not a module.
See this from the Go Modules Reference
A module is a collection of packages that are released, versioned, and distributed together. Modules may be downloaded directly from version control repositories or from module proxy servers.
A module is identified by a module path, which is declared in a go.mod file, together with information about the module's dependencies. The module root directory is the directory that contains the go.mod file.
And
A module is defined by a UTF-8 encoded text file named go.mod in its root directory.

Go Modules for microservices

I am developing multiple microservices, which require different modules (which shall be available like modules on github, but private)
My first tests with Go were all located within one package, which gets quite messy after some time
I'm coming from the Java side of programming - with loads of packages - which keep stuff clear and clean.
(This also works with public modules like on github.com/xyz/module1 github.com/xyz/module2 github.com/xyz/module3)
I just need this for private modules - how can I do so?
This is what I tried yet:
Directory of my go sources:
C:\my\path\to\go\src\
In this dir I have multiple subdirs containing modules (actually more than listed here)
my-module1
my-module2
my-module3
For each folder I called go mod init but I get the message that
package my-module1/util is not in GOROOT (c:\go\src\my-module1\util)
which is obviously right, as my private libraries reside in C:\my\path\to\go\src\
Importing packages from github with go get ... is working without troubles (those packages will be loaded but copied to c:\go\src)
Working with all files in one folder works but is not the desired solution (I need to create multiple microservices therefore I want to be able to create different projects with custom executeables and or tests)
What am I doing wrong?
If more information is needed I will provide it - just let me know what
NOTE: packages without go file in package main cannot be installed via go install. This system looks pretty confusing to me - as modules cannot be found...
finally i created a multimodule
means i have a root folder (lets call it root) which contains a go.mod file
this defines the root module
it requires all my submodules
and it replaces the absolute path into a relative.
root
* aa
* ab
* bc
main gets defined as
module root
go 1.15
require (
root/aa v0.0.0
root/ab v0.0.0
root/bc v0.0.0
)
replace (
root/aa => ./aa
root/ab => ./ab
root/bc => ./bc
)
all the submodules have a very simple definition (this is equal for all, as long as you do not have any dependencies)
module root/aa

Importing local go module of external service

The background:
Two Applications - A and B
Application 'A' contains two go.mod files
A/pkg/test/go.mod: (I keep here application specific structures which are gonna be reused by another services willing to integrate)
module A/pkg/test
go 1.14
require (
some_dependencies vx.x.x
)
A/go.mod: (root module importing pkg/test as local module)
module A
go 1.14
require (
A/pkg/test v0.0.0
)
replace A/pkg/test => ./pkg/test/
Now Application 'B' would like to re-use Application's A pkg/test package by simply importing it
The Adventage:
This solution lets any integrating services pull only dependencies of pkg/test module instead of importing whole application A tree
Current Solution:
Application 'B' imports pkg/test module of Application 'A' using following go.mod:
module B
go 1.14
require(
some_dependencies vx.x.x
A/pkg/test v0.0.0
)
replace A/pkg/test => gitlab.com/A/pkg/test v0.0.0-02345798575346-72cs44671e34
Now I really do not like using commit-timestamp_commit-sha approach here.
The problem:
I would like to use TAGS in order to import A/pkg/test module.
Repository A has a tag, say v2.0.0, created. When I replace v0.0.0-02345798575346-72cs44671e34 with v2.0.0, after running go mod tidy/download I am getting following error output:
reading gitlab.com/A/pkg/test/pkg/test/go.mod at revision pkg/test/v2.0.0: unknown revision pkg/test/v2.0.0
The question:
I assume bad package naming/module naming/tagging etc. might lead to such error. The question is what am I missing here in order to make it clear and work?
To take a nested go-modules package within a git repo, just add a tag to the directory that contains the go.mod file - and then append your version.
So in your case, the directory is A/pkg/test and lets say you wanted to use semver v0.0.1 you tag like so:
git tag -a "A/pkg/test/v0.0.1" -m "initial test checkin"
git push origin --tags # push all local tags
# git push origin "A/pkg/test/v0.0.1" # push a single tag
Please Note: from the Go wiki Should I have multiple modules in a single repository? - Russ Cox (the creator of vgo i.e. today's go-modules) warns:
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.

Resources