In Go, it is common that some packages are versioned. So a program might look like this:
package main
import (
"github.com/go-gl/gl/v3.3-core/gl"
"github.com/go-gl/glfw/v3.2/glfw"
)
// ... do stuff
Sometimes, I might want to update the version of glfw. Lets imagine GLFW 3.3 bindings come to Go and I want to update from 3.2.
I might have multiple Go files in a project all using glfw. I don't want to go into each of them and update the version of the import by hand. Ideally I wouldn't be copying that long path around, either, and I could define it in one place per project.
Maybe I could write a script to find+replace "github.com/go-gl/glfw/v3.2/glfw"
Maybe I could template the file with Genny
Maybe I could create a symlink inside the root Go path "glfw" -> "github.com/go-gl/glfw/v3.2/glfw", update it when changing version, and just use import "glfw"
but this information then lives "outside" the project, so no-one cloning my project knows what version to use
but this is a global change and I might have multiple projects which want to depend on different versions
Ideally I would be able to do something like this in each source file:
package main
import (
$gl
$glfw
)
And in some project-level dot file, something like:
gl=github.com/go-gl/gl/v3.3-core/gl
glfw=github.com/go-gl/glfw/v3.2/glfw
Or, a command-line argument attached to go build defining constants that could look something like:
go build -Dgl=github.com/go-gl/gl/v3.3-core/gl -Dglfw=github.com/go-gl/glfw/v3.2/glfw
How is everyone else handling this currently?
See github.com/golang/go/wiki/Modules for the recommended way of managing package versions.
Related
I was trying to follow a tutorial on using aws with go. When I gave the command "go get github.com/aws/aws-sdk-go/aws", I still got failure to import. I was left wondering if the "go get" succeeded or not.
Following the guidance provided in the answers here, I updated my GOPATH variable and now the import succeeds.
Your hello.go should start something like this:
package main
import (
"github.com/aws/aws-sdk-go/aws"
)
See this example in the playground. So when importing a remote module use the full path in the import statement.
Re another question you asked in the comments (and I mentioned in comments to another of your questions) - go mod init initialises a module. See this article for information. When using modules, GOPATH is no longer used for resolving imports (see this article). So basically GOPATHis the old way of doing things; go modules is the new way (it solves a lot of issues but having the two approaches can be confusing to someone new to the language because some tutorials assume GOPATH and others use modules).
For completeness you have other questions about environmental variables. I think this may be due to a misunderstanding about how these work. When you enter export GOPATH=XXX in a terminal session that will update the environment within that session (that is that terminal window only; it will not have any impact on any other sessions you have open, including vscode). If you want to set a system wide environmental variable then you need to update a configuration file (often ~/.bashrc but this depends upon your OS see this article for info). After doing that restart the applications (or ideally youre PC) to pick up the new setting.
When you run go get github.com/aws/aws-sdk-go/aws; go tool will download the package into $GOPATH/src/github.com/aws/aws-sdk-go/aws directory.
That is why you need to import package by its full name (which is same as path to files under $GOPATH/src directory:
import "github.com/aws/aws-sdk-go/aws"
You can find more about how source code is organized under GOPATH and how imports work here and specifically about remote (github) imports here.
NOTE: GOPATH resolution works only when your project doesn't use modules (you don't have go.mod file). If you're following a tutorial and it doesn't mention use of modules above should work fine.
I'm writing my first Go code which among other things, sends an email. After finding out that the package net/smtp only supports Plain Auth (but some providers like outlook doesn't support it), I asked for a solution and got pointed out to https://gist.github.com/andelf/5118732.
That code works like a charm, but as it's not something written by myself, I would like to add it in a separate file and just reference it in my main.go.
What's the right approach to have multiple files in the same package? I don't want to create a different package just for that code, first because it's not mine, and secondly, because I think it's an "overkill" approach, isn't it?
I thought that as long as the files are in the same directory, I could have many *.go files, but it seems it's not working out. If I just create a file with the content of that gist, the compiler fails because expected package, found import. If I add something like package auth, then it fails because found packages auth (auth.go) and main (main.go)
So, what's the general practice in this situations? Just create packages for everything?
You can have only one package in a directory, and it looks like you don't need a package for this addition, so you can simply put that in a separate file, and add package main at the top. Having a main package and putting everything under it works up to a point. As things get larger, you have to break it up into self-contained packages.
If your current working directory is in GOPATH, then you can just add new go file with same package name main.
If your current working directory is not in GOPATH, you can still put them in multiple go files and when you run the program, you should use go run *.go instead of just go run main.go.
There are also other options which you can refer Run code with multiple files in the same main package in GoLang for detail.
I see that in Go you can import packages directly from Github like:
import "github.com/MakeNowJust/heredoc"
I understand that the path I am seeing in import line is not an URL, but only the path the package is located in (normally relative to $GOROOT/src/pkg or $GOPATH/src). So the package heredoc is most probably located in the directory $GOPATH/src/github.com/MakeNowJust/heredoc.
Now let's say that the package developer decided to migrate the code repo to Bitbucket. So now the library URL is bitbucket.com/muchMoreCoolerName/heredoc. He also added some new features to the code repo.
My question is how will you get the updated code?
The only solution I can think of is changing all the imports to new URL and doing go get again. But changing the code for library update seems a little inconvenient.
If you just use go get and then import, there is no way around it, you will have to update the import paths to get the new code. However, if you use vendoring(a technique to keep your dependency with your code and also distribute it with them) you would be isolated from that move at least until you update. When you want to update, you could use a vendor functionality to keep the old import path but to sync with the other repo.
Frankly, I'd still use vendoring in anyway and just do a search and replace for the old import path when I decide to update, this is not that hard.
EDIT You can also use dep to manage dependencies if you haven't transitioned to modules yet.
In golang import statements, is it better to have something like:
import(
'project/package'
)
or
import(
'github.com/owner/project/package'
)
for files local to your project?
For either option, why would you want to do one over the other?
I ask this because while it's easy and more intuitive to do the first one, I've also seen a lot of big projects like Kubernetes and Etcd do it the second way.
These are exactly the same as far as the go build tools are concerned. The fact that package is in the directory
$GOPATH/src/github.com/owner/project/package
or in the directory
$GOPATH/src/project/package
makes no difference.
The only difference is that with the former you can use go get to fetch the source automatically, and the latter you have to clone the code yourself.
What you don't want to use are paths relative to the project itself, like
import "./project/package"
That is not compatible with all the go tools, and is highly discouraged.
I want to basically copy the parse and template packages from the golang source: http://golang.org/pkg/text/
I want to be able to just play around wit the code and hack on it for fun and learning etc.
Can someone tell me how to go about doing this?
Could I just copy the package folders and then somehow move it to my own package like:
$GOPATH/src/github/user/parse
$GOPATH/src/github/user/template
Is this a safe way to do this? How will it build?
Yes, you can just copy the folder like you've described.
When you import it in your application, you just use your new import path:
import (
"github.com/user/parse"
"github.com/user/template"
)
It is completely safe to do that. Just Go ahead and code!
Ps.
I assumed your path would actually be:
$GOPATH/src/github.com/user/parse
since the domain (.com) will also be included in the go get path if you use github to host your package.
Ps2.
Remember to update the imports in the github.com/user/template package to refer to your new parse package instead of the original one.