
Goop – Dependency Manager for Go - alixaxel
https://github.com/nitrous-io/goop
======
jameskilton
What does this offer that godep doesn't?

~~~
shurcooL
Or, in what ways does the design philosophy here differ enough to warrant a
separate project instead of making PRs to godep?

~~~
raingrove
Because we love choice?

Godep wants you to touch your GOPATH. For example, `godep save` saves
revisions of packages currently installed in your GOPATH and `godep restore`
downloads packages into your current GOPATH. If you don't want to pollute
global GOPATH, you will have to change it. This works for some people, doesn't
for others.

Goop doesn't want you to worry about GOPATH. Goop also encourages you to
explicitly state which packages you are using in the Goopfile, rather than
"capturing" what is already in use.

~~~
chimeracoder
It's not really clear from the documentation/README how this works under the
hood, so for now I have to just go by what you're saying here until I have
time to actually take a closer look.

First off, I will say that I'm not a great fan of godep, so I'm not looking to
advocate for it. That said:

> Godep wants you to mangle with your GOPATH. For example, `godep save` saves
> revisions of packages currently installed in your GOPATH and `godep restore`
> downloads packages into your current GOPATH. If you don't have to pollute
> global GOPATH, you will have to change it. This works for some people,
> doesn't for others.

Your $GOPATH is a list of directories, not a single directory. This is almost
never useful in practice (most people should just use a single directory as
their GOPATH). However, for what you're trying to do here, that would be far
simpler than introducing a third-party tool, especially one that requires
adoption from all project contributors.

> Goop doesn't want you to worry about GOPATH.

The $GOPATH is technically not part of the Go language (spec), but it is a
language-wide idiom respected by all build tools. I'd be very nervous about a
project that eschews such firm idioms in favor of its own inventions.

~~~
eikenberry
> Your $GOPATH is a list of directories, not a single directory. This is
> almost never useful in practice (most people should just use a single
> directory as their GOPATH).

I disagree. I use and recommend a 2 directory GOPATH setup. The first path
being the one where all 'go get' packages are installed and the second being
where you put your packages. I've found keeping these separated makes long
term management easier.

~~~
NateDad
Why? "my code" is in $GOPATH/src/github.com/natefinch/ ... all code that is
not "my code" is in other directories. Why bother having to switch over to
some other gopath to get there?

Go import directories, are, by definition, unique. My work code is under
github.com/juju/. Why should I put labix.org/v2/mgo under some other root
path? They're unique directories either way.

------
vmiroshnikov
If someone looks for an alternative, consider this kit:

[https://github.com/pote/gvp](https://github.com/pote/gvp) \- virtualenv in
go's world

[https://github.com/pote/gpm](https://github.com/pote/gpm) \- pip in go's
world

------
dead10ck
I'm curious why so many of these Go dependency managers are popping up.
Doesn't go get download all dependencies automatically? Why are these third-
party dependency managers necessary?

~~~
collinvandyck76
Because 'go get' does not allow you to point to a particular revision. It
downloads the latest / HEAD commit for that dependency and sticks it into
${GOPATH}. These dependency managers are all aiming to fix that problem, and
some of them, I believe, transitively.

~~~
jzelinskie
For git (and probably others) It actually looks for a "go1" tag, and if not
there it uses the head of master.

I honestly don't care for all these version managers. If I didn't trust the
author of whatever library I'm pulling in to keep their API stable, then I
wouldn't use that library or I'd preemptively fork. This is actually a
language convention and if more people were familiar with it, there would be
even less issues (though I haven't ever had any personally). If you're
interested in helping the community familiarize themselves with Go's language
conventions, I made a package[0] that developers should read after going
through the Go Tour. It's meant to teach best practices and conventions for
library design in Go.

[0]
[https://github.com/jzelinskie/conventions](https://github.com/jzelinskie/conventions)

~~~
grey-area
You are arguing for versionless libraries? AFAIK the go maintainers tried that
with golang itself in the beginning, and gave up on it, because it's not
practical in real world use when APIs are changing quickly and outsiders want
to know if they can update without breaking. There are very few libraries
which have managed this in the past and have remained at version 1.x for their
lifetime.

It's interesting that go get supports reading version tags, though it's a bit
pointless to support them for language changes, since go1 is stable, go2 is
unlikely to arrive for years, and Gofix would be best used to fix any issues
with a major transition like that anyway. So in practice this feature is not
used.

It'd be nice if go get instead supported reading version tags for packages,
and had some simple scheme for getting the latest compatible version using
semver and versioning import dirs, rather than simply pulling the latest
master. I think to do that they'd have to adjust go get and go build/run
though, perhaps to add a lock file and to take dirs like
github.com/foo/bar-v1.2 into account. Simple versioning would not be a
difficult change or an incompatible one, it just wouldn't deal with the very
difficult issues of conflict resolution on larger projects, which I think was
the golang team's objection (correct me if I'm wrong). I do see why they don't
want to introduce a half-baked solution without dependency resolution.

At present either library authors are expected to never break compatibility
_ever_ (your proposed solution), or everyone has to update their code when
they do. This particular detail seems like undesirable behaviour or an
unresolved problem in golang to me, rather than a carefully thought out
convention. Just because that's the way it is doesn't mean that's the way it
should be.

~~~
jzelinskie
I don't think they've given up on the idea considering there still is no
official version management. To give up would mean that they're doing
something else and AFAIK this is still best practice. The early Go team did
believe this would be an okay idea, but over time everyone has noticed that it
may not be for the best. However, the Go team also punted on solving the
problem while thinking that the community will figure something out. The
problem is that "go get" is already built into our standard toolchain. The
moment you start using a dependency manager, now the official toolchain
workflow is broken and you've fragmented the ecosystem. If people really want
a solution to this problem they need to prod the Go team and finally get an
official decision made and merged into the go tool, rather than just creating
their own binary.

~~~
grey-area
_I don 't think they've given up on the idea considering there still is no
official version management._

Sorry, that wasn't clear, I was talking about the language itself - the
language is now versioned, but it wasn't for initial releases - they had
weekly snapshots, then moved to formal versioning and gave up on the idea of
being version-less. See these slides about version 1:

[http://talks.golang.org/2012/go1.slide](http://talks.golang.org/2012/go1.slide)

What holds for the language holds also for libraries I think - having explicit
versioned releases and being able to sometimes break backwards compatibility
is really useful, esp. if others can pin whatever version they import easily
and migrate at their own pace.

I think it's good people are experimenting with pkg versioning - if someone
comes up with an elegant solution and deals with most of the edge cases, it'll
probably get into the bundled tools like go get eventually, or people will
stop using go get and use another better tool. go get is not essential for
fetching go libraries, it's just the blessed method.

------
alecthomas
Config file is nicer than godep; easily generated with a bit of shell. Quite
nice.

------
kylered
In case anyone is interested, we open sourced this one about a year ago:
[https://github.com/VividCortex/johnny-
deps](https://github.com/VividCortex/johnny-deps)

------
imslavko
It says it is inspired by Bundler but in what ways? I am curious as I didn't
use much of neither bundler nor goop but I have heard the constraints
resolution lays in the heart of bundler.

~~~
raingrove
You are right. Unfortunately, constraints resolution isn't something that can
be implemented in a practical manner until there is a standard versioning
scheme (there isn't much you can do with git hashes) and a standard dependency
manifest file that every go project adopts.

Goop has `Goopfile.lock` and `goop exec`, inspired by Bundler's `Gemfile.lock`
and `bundle exec`.

~~~
grey-area
_until there is a standard versioning scheme (there isn 't much you can do
with git hashes)_

Couldn't you use tags for versioning? Often people use tag v1.1.1 etc?

~~~
cstrahan
See: "and a standard dependency manifest file that every go project adopts"

You need some way to create a complete dependency graph for a given project.
If your project has a list of its immediate dependencies, but those
dependencies in turn require specific versions of other packages, how do know
what those versions are? You need some consistent way of getting this
metadata.

There are a couple solutions, but a few that come to mind: each project stores
their deps metadata in a consistent location in their repo, or there's some
central package repo (a la RubyGems) where such metadata can be queried.

For any solution to work, all of your dependencies (both direct and indirect)
need to opt in to the same metadata scheme, or the system falls apart.
Unfortunately, there isn't any consensus in the Go community on how to fix
this.

This is what the parent meant by "there isn't much you can do with git
hashes."

------
dz0ny
set -x GOPATH (PWD)/.vendor set -x GOBIN (PWD)/.vendor/bin

And committing stuff in git when it matters.

gvm is also nice for testing stuff with different versions of go.

~~~
rem7
I also setup my path per project. And vendor all my deps under _vendor And for
getting libraries instead of doing go get I use git subtrees like so:

git subtree add --prefix _vendor/src/github.com/crowdmob/goamz
[https://github.com/crowdmob/goamz.git](https://github.com/crowdmob/goamz.git)
master --squash

------
sswaner
Hope Gwyneth Paltrow doesn't get upset about the name.
[http://www.goop.com](http://www.goop.com)

------
aosmith
I've been doing basically the same thing by creating src/ and pkg/ directories
and using this alias:

go='GOPATH=`pwd`:$GOPATH go'

~~~
dengnan
In this case, try to run a `go get`, it will install everything into your
current directory's bin/ directory.

~~~
aosmith
go get still works but it uses the src/ ... AFAIK there's no bin/ with go...

------
dkulchenko
Looks fantastic, thanks for this!

------
leccine
Goop for teh rescue! The only trouble I had with go is the dependency
handling. I wish people realize how Erlang's way of dealing with this is
superior.

~~~
macrael
What does Erlang do?

~~~
leccine
Gets you downvotes on HN.

~~~
macrael
Sill like to know what Erlang's dependency management is :)

~~~
leccine
there is no import, what you are calling is either there because you included
the path to the beam file when you are starting up the VM or it is not there
and calling the function returns an error. all of the libs are organized to
the module:function structure and you cannot chain.

