Using local packages with gb - go

I'm starting a new project and considering gb as my build tool but it doesn't appear to be integrating very well with vscode...
I've referenced 3rd party dependencies no problem using gb vendor fetch but as for creating local packages, this is proving a little trickier! Am I missing something obvious?
Here's my local src directory:
src
/cmd
/model
calc.go
/server
server.go
The following code compiles and creates a bin\server.exe file successfully but the import path isn't picked up, nor does gocode recognise it
Here's the server code:
package main
import (
"cmd/model" // not a happy reference...
"fmt"
)
func main() {
fmt.Println(model.Add(1, 2))
}
Here's the model code:
package model
func Add(a int, b int) int {
return a + b
}
I've found what appears to be a similar issue on Github (https://github.com/joefitzgerald/go-plus/issues/325) and while nsf's solution sorts out auto-complete (post import), the import statement itself still claims to be searching in the GOROOT and GOPATHs.
Any ideas?

Thanks to an answer from lukehoban here https://github.com/Microsoft/vscode-go/issues/249 I was able to get my environment working.
I simply created a settings.json file under the .vscode directory (which will now have to be checked in) into which I've configured:
{
"go.gopath": "${workspaceRoot}"
}
This makes me feel unclean and it still doesn't provide a way to reference both 3rd party dependencies and local packages together...

Do not try to work against Go, work with Go.
First of all give all your packages fully qualified import paths. Go is designed around global import paths, do not try to force Go into using flat hierarchies or even relative paths.
You can point to your import path repository endpoints either directly or by using Go's remote import path mechanism. BTW, if you happen to run a self-hosted GitLab instance, it supports remote import path meta tags out of the box.
I prefer glide, but maybe the following is possible with gb, too. Certainly something simililar will be possible with the upcoming go dep: You can point to ssh+git endpoints and others using glide's repo stanza. Frankly I have no idea if gb supports an equivalent mechanism, but if it doesn't this is a good reason to reconsider.

Related

Go module is usable even after deleting the module repo from GitHub

I was learning go modules so I created a very basic module with an Add() function and published it on GitHub.
The repository was https://github.com/umermasood/nummanip (it throws 404) becaused I deleted the repo from GitHub.
But I am still able to use the calc package from the module.
package main
import (
"fmt"
"github.com/umermasood/nummanip/calc"
)
func main() {
fmt.Println(calc.Add(1, 2))
}
Output:
3
Above code in the Go Playground: https://go.dev/play/p/gMYD6Jirz_n
What is causing this behavior?
The Go Module Mirror is keeping your module downloadable.
See the FAQ item below.
I removed a bad release from my repository but it still appears in the mirror, what should I do?
Whenever possible, the mirror aims to cache content in order to avoid breaking builds for people that depend on your package, so this bad release may still be available in the mirror even if it is not available at the origin. The same situation applies if you delete your entire repository. We suggest creating a new version and encouraging people to use that one instead.
Source: https://proxy.golang.org/

PromQL Module Missing

I am trying to use the promql package here
package main
import (
"fmt"
"github.com/prometheus/prometheus/promql/parser"
)
func main() {
fmt.Println("Hello")
parser.ParseExpr("foobar")
}
Having trouble importing. This is the error:
no required module provides package
github.com/prometheus/prometheus/promql/parser; to add it:
go get github.com/prometheus/prometheus/promql/parser (compile)
I tried to run go get github.com/prometheus/prometheus/promql/parser as suggested but it fails.
go get: module github.com/prometheus/prometheus#upgrade found
(v2.5.0+incompatible), but does not contain package
github.com/prometheus/prometheus/promql/parser
Here is my go.mod currently:
module foo.com/bar/parser
go 1.17
require github.com/prometheus/prometheus v2.5.0+incompatible // indirect
Use go get github.com/prometheus/prometheus#83032011a5d3e6102624fe58241a374a7201fee8 (that commit is the latest release at this point in time, v2.33.4)
The reason this is needed is that
This is a known issue with Go Modules. The semantic versioning of Prometheus versions the behavior of Prometheus as a server, not its code as a library. By changing the module path to v2, we would suggest that Prometheus obeys the contract of Go Modules as a library, but it doesn't, i.e. there are many breaking changes to expect even in a minor release.
and:
Prometheus was not intended to be used as a library. Now that has changed, and it is intended to be used as such, even if we do not accept all general-purpose contributions.
The error you are seeing is because go get is grabbing an old release v2.5.0 by default which was released back in 2018 and does not include the parser package. This happens because the versioning scheme used by Prometheus does not align with that assumed by Go.
See this issue for additional info.

How can you have two copies of same package that cannot be used for having different namespaces

Here is a quote from a blog post:
Enforce vanity URLs go get supports getting packages by a URL that is
different than the URL of the package's repo. These URLs are called
vanity URLs and require you to serve a page with specific meta tags
the Go tools recognize. You can serve a package with a custom domain
and path using vanity URLs.
For example,
$ go get cloud.google.com/go/datastore
checks out the source code from
https://code.googlesource.com/gocloud behind the scenes and puts it in
your workspace under $GOPATH/src/cloud.google.com/go/datastore.
Given code.googlesource.com/gocloud is already serving this package,
would it be possible to go get the package from that URL? The answer
is no, if you enforce the vanity URL.
To do that, add an import statement to the package. The go tool will
reject any import of this package from any other path and will display
a friendly error to the user. If you don't enforce your vanity URLs,
there will be two copies of your package that cannot work together due
to the different namespace.
package datastore // import "cloud.google.com/go/datastore"
Can someone explain what the last line means?
If you don't enforce your vanity URLs,
there will be two copies of your package that cannot work together due
to the different namespace.
Or demonstrate it in an example?
It's pretty simple.
If your package is hosted at, say github.com/foo/bar, and you have vanity URL foo.com/bar, then someone could do both:
import "github.com/foo/bar"
and
import "foo.com/bar"
This will be problematic if you have different files or packages that import the same package at different paths.
Imagine these two files in the same package:
// foo.go
package foo
import "github.com/foo/bar"
func frobnicate(x *bar.Something) { /* ... */ }
// bar.go
package foo
import "foo.com/bar"
func widget() {
x := *bar.Something{}
frobnicate(x) // compilation error: cannot use x (type foo.com/bar.Something) as type github.com/foo/bar.Something
}

Workflow for Google Cloud Functions with Golang

When developing a small Google Cloud Function in Go. I noticed it will throw an error if you have everything in your package main - eg. import "<whatever>" is a program, not an importable package
So the solution is switch it out to its own package, then deploy. If something goes wrong, throw it back into a package main and work on it locally, then switch it back.
Is this the best workflow? The other option i see is possibly making the Cloud Function its own module and importing it into a main.go file.
I was able to create a cli folder in project's top level and then put main.go file using package main and main() function inside it. That allowed me to have separate file cloud_functions.go in root with different package name that has one or more google cloud functions in it.

Importing prefix golang?

From what I understand, golang imports modules like
import (
"bitbucket.org/user/project"
"github.com/user/project"
)
is there a way to import modules in all files, without explicitly typing an absolute remote location out, from
1) a single remote location?
2) multiple locations?
So for 1), you could specify somewhere that the host is github.com/user and any import that is not a default library and doesn't have a remote prefix is prefixed by github.com/user. Or have a prefix_variable + relative/path and be able to set the prefix_variable somewhere?
So like
// in some config file
github = "github.com/user/"
bitbucket = "bitbucket.org/user/"
// imported in file
import (
bitbucket + "project" // "bitbucket.org/user/project"
github + "project" // "github.com/user/project"
)
or
// in some config file
default = "github.com/user"
// imported in file
import (
"bitbucket.org/user/project" // this has a remote prefix, so default prefix is not added
"project" // "github.com/user/project"
)
Unfortunately to my knowledge there is no way to do this in the way you have stated. There is a discussion in Google Go Group which is somewhat related Go Packaging: building a great packaging story which might give you some ideas of the thought process for why this cant be done (assuming you were not aware of this already).
I actually have a related problem which is associated with producing a build for two different server environments, one for Google App Engine and one for a local linux development environment sharing packages (imports) and I am still looking for the solution, hence watching this type of discussion.

Resources