Hello everyone !
I'm new to golang and I have some questions about the workspace and the dependencies management.
I've read that GOPATH is the location of my workspace, where all of my go code belongs (personal project and dependencies of all of these projects).
If I want to push one of my project on github, will I push only my project source code or will I also push the dependencies ? If I must push only my code, how another developer who wants to clone my repo can find the list of my dependencies and use the rights versions ?
Can I have two projects using two different version of the same library ? (It seems to be impossible if all of my project and dependencies are in the same folder).
Thanks for your answers !
评论:
neoasterisk:
rafoufoun:Is the project a library/package or a binary?
neoasterisk:It could be both (don't have one yet, just asking for my knowledge).
Let's say I want to develop a script which will be deployed as a binary. I can't understand where I should put this code and the dependencies I could have
rafoufoun:Let's say I want to develop a script which will be deployed as a binary
Go's default source code organization is based around the concept of a monorepo. That means that you have a folder (by default ~/go) and under that folder you have
src
,pkg
andbin
. All source code for any Go project lives under thesrc
folder. So your project will be under~/go/src/github.com/rafoufoun/projectname
and maybe it includes a dependency which lives under~/go/src/github.com/boltdb/bolt
. If someone doesgo get github.com/rafoufoun/projectname
that will also fetch the dependency.The case of binary, it is the easiest case because when you compile
github.com/rafoufoun/projectname
it will also include the boltdb dependency in the binary. So all you have to do is distribute that binary and you are done.You should treat the
src
folder as a huge monorepo. If many projects share theboltdb
dependency then all of them will find the dependency in the exact same path~/go/src/github.com/boltdb/bolt
. When working with a monorepo, ideally all projects should use the same exact version. Go's version 1 compatibility guarantee and general philosophy of minimizing dependencies and focus on backwards compatibility make this easier.Obviously in practice, things are not perfect. You might end up having to use a shady or unfinished project that keeps having breaking changes every time you do
go get
. I'd argue that you shouldn't even be using such a project as a dependency but if you really should then you should vendor that dependency. That means that you are gonna have a vendor folder under your project folder and under that folder it will be the pinned dependency. So it will look like~/go/src/github.com/rafoufoun/projectname/vendor/github.com/shady/project
. That will allow you to doimport github.com/shady/project
in your code and guarantee that it will always use the version under the vendor folder.If I want to push one of my project on github, will I push only my project source code or will I also push the dependencies ?
It depends on your style. Personally when I vendor dependencies I like to commit the vendor folder. That makes it much easier to have the whole code in the repo.
If I must push only my code, how another developer who wants to clone my repo can find the list of my dependencies and use the rights versions ?
If the other developer does
go get github.com/rafoufoun/projectname
that will also fetch all the dependencies. If you worry about the dependencies having breaking changes then you should vendor them as I described above.Can I have two projects using two different version of the same library ? (It seems to be impossible if all of my project and dependencies are in the same folder).
Vendor the different version of the library under each project that needs it.
I hope that helps.
neoasterisk:That helps me A LOT !
The way Go handle dependencies is quite confusing at first. What I understand is that it's made like this according to the philosophy of minimizing dependencies, and made possible with the backward compatibility of Go 1.
Now I'm more comfortable about having all of my Go projects into the same workspace since in "emergency case" I can vendor the dependencies I want.
And since a 'go get' on my cloned project will fetch all the dependency and install them in the GOPATH, no worries about that neither.
Your answer is perfect thanks again ;).
One more thing, where can the 'go get' command find the list of all the dependencies I'm using to get them back if they are not in the GOPATH ?
rafoufoun:What I understand is that it's made like this according to the philosophy of minimizing dependencies, and made possible with the backward compatibility of Go 1.
It is made like this because Go is designed by Google to help solve Google's problems and Google is using a monorepo.
Simplicity, minimizing dependencies, focus on backwards compatibility and stability are indeed included in the Go philosophy but it has nothing to do with why Go uses the monorepo method.
One more thing, where can the 'go get' command find the list of all the dependencies
Go get treats the source code as the only source of truth. If go get sees in your code
import github.com/boltdb/bolt
then it will try to fetch that dependency. So from your perspective all you ever have to do is typego get
.If you really need to know the names of the dependencies of an unknown/large project then you can use some tools like go list or use something like the web interface of go doc with the
?imports
parameter: https://godoc.org/github.com/boltdb/bolt?imports
neoasterisk:Thanks ! I assume that if a library is in the GOPATH and vendored, the vendor one take the priority in the dependency resolution ?
You helped me a lot here to get started
I assume that if a library is in the GOPATH and vendored, the vendor one take the priority in the dependency resolution ?
Yes the go toolchain looks first in the vendor folder for imports before looking under GOPATH/src.
