►
Description
Please see this link for more information: https://github.com/liggitt/gomodules/blob/master/README.md
Thank you Jordan Liggitt for the fantastic overview!
A
A
B
See
that
we've
done
yes,
great
all
right.
So
this
is
a
whirlwind
tour
of
go
modules,
all
of
the
examples
and
links
and
everything
will
be
posted
after
the
fact.
So
don't
worry
if
you
miss
something
all
this
will
be
available
for
you.
I
also
want
to
just
declare
upfront.
This
is
my
current
understanding.
I've
spent
the
last
several
weeks
or
month,
or
so
digging
into
this.
It
is
entirely
possible.
B
I've
misunderstood
something
so
I
reserve
the
right
for
published
errata
afterwards,
all
right
so
very
quickly,
you're
all
probably
familiar
with
the
old
way,
which
is
go
path.
So
that's
where
all
your
source
code
is
located
in
one
tree
and
all
your
modules
have
to
be
in
that
one
place
and
are
relative
to
each
other
and
it's
kind
of
one
big
ball
of
code,
and
so,
if
you
had
a
couple
components,
it
might
look
like
what
you
see
here.
B
So
I've
got
this
one
component,
which
is
my
main
function,
and
it
has
a
sub
package
with
a
helper
that
prints
and
stuff,
and
then
it
also
depends
on
this
other
component,
which
is
pretty
useless,
but
we're
definitely
going
to
call
that
that
function
and
all
of
these
live
underneath
my
go
path,
so
they
must
be
located
relative
to
go
path
by
there.
There
important
that,
and
so
when
I
run
this.
B
B
B
Well,
we
don't
really
have
a
way
to
deal
with
that,
and
so
what
you
usually
have
to
do
is
have
completely
different,
go
pads
per
project
or
you
can
vendor
all
your
dependencies
into
a
vendor
subdirectory.
Neither
of
those
are
super.
Terrific.
You
end
up
with
lots
of
duplication
and
it's
kinda
hard
to
manage
another
potential
problem.
B
What,
if
you
don't
want
to
structure
your
directory
tree
like
go
path
requires
well
tough,
you
don't
always
get
what
you
want
and
then,
finally,
what
if
the
source
in
go
path,
drifts
from
its
authoritative
source,
so
I
mentioned
before,
like
I,
can
develop
locally.
I
can
I
can
change
stuff
under
here,
but
what
if
this
wasn't
the
component
IO
and
what?
B
If
this
was
like,
C
advisor
or
T
log,
or
something
like
that,
if
I
change
that
it
definitely
gets
work
linked
into
my
build,
but
it's
easy
to
accidentally
drift
from
the
authoritative
source,
so
that
can
be
good
or
bad,
depending
on
whether
you're
counting
on
locally
or
not,
and
so
then.
Finally,
a
few
questions
about
how
go
resolves
pads
if
Co
is
trying
to
figure
out
what
the
full
import
path
of
that
is
the
way
it
does.
It
is
looks
at
its
relative
path
to
go
path.
B
B
Let's
try
removing
these
from
my
go
path
and
see
what
happens
if
I
build
them
somewhere
else.
So
I'm
gonna
check
that
same
a
repo
out
in
some
random
path,
so
I
just
made
up
a
path
cloned
it
into
there
and
now,
when
I
try
to
run
you
get
the
error,
you
would
expect
it
you're
trying
to
build
something.
That's
outside
of
a
go
pass
and
go
has
no
idea
that
the
helpers
folder
is
actually
this
package.
It
has
no
idea
how
to
find
the
the
other
B
component
that
I
needed.
B
B
It
figures
it
out
relative
to
the
declared
module
of
the
closest
go
mod
file,
so
the
helpers
subdirectory,
if
it's
trying
to
figure
out
what
the
package
of
that
is,
it
walks
up
the
tree
until
it
finds
this
go
mod
file
says:
oh,
this
is
declaring
this
module.
Therefore,
that
must
be
github.com,
slash,
Liggett
/,
a
/
helpers.
That
is
the
path
of
this
helpers
package.
B
But
it
actually
was
able
to
locate
github.com
slash
like
a
/
b,
which
is
interesting.
So,
let's,
let's
look
at
what
that
actually
did
to
our
go
mod
file
when
we
ran
go
notice
that
we
were
using,
we
were
importing
a
package
that
wasn't
represented
as
a
dependency
in
our
module
file
and
it
resolved
that
found
that
the
current
tagged
version
of
that
was
v10
and
it
added
it
to
our
go
mod
file
automatically
as
a
require
statement.
B
B
If
you're
trying
to
read
a
mod
file
just
like
import
statements,
you
can
have
each
on
its
online
or
you
can
group
them
into
a
block,
so
multiple
require
lines
or
several
and
a
block
are
equivalent
and
the
version
that
can
be
specified.
There
can
be
any
tag
or
branch
or
sha.
Anything
that
go
can
resolve
from
version
control
can
be
put
there
and
the
next
time
that
go
resolves
the
module
graph.
It
will
turn
it
into
its
canonical
form.
So
if
you
want
to
specify
a
particular
sha
or
branch,
you
can
do
that.
B
You
can
also
so
when
we
did
this,
we
just
said
go
run
and
it
found
the
latest
version
of
this
module.
If
we
had
a
particular
version
in
mind,
we
could
have
used,
go,
get
to
express
this
and
specified
a
particular
version,
and
it
would
have
added
that
require
statement
as
well,
rather
than
just
automatically
grabbing
the
latest.
So
this
adds
the
ability
to
specify
versions
as
part
of
GoGet,
which
is
nice
instead
of
always
grabbing
master.
B
All
right,
so
it
recorded
that
we
required
this
version,
but
then,
if
we
don't
have
a
go
path,
where
did
the
B
dependency
actually
get
put
and
it
got
put
in
a
module
cache
which
is
located
under
our
go
path?
And
you
can
look
at
it's
just
a
directory
full
of
files,
segmented
by
module
path
and
you'll
notice
that
the
version
information
is
recorded.
So
we
no
longer
have
the
problem
with
not
being
able
to
hold
on
to
multiple
versions
of
a
component.
B
B
A
B
Now
you
might
be
looking
at
this
saying,
but
I
love,
my
hermetic
builds
I.
Don't
want
builds
talking
to
the
network
at
all,
and
if
that's
you,
there
are
tools
for
you.
The
go
proxy
environment
variable
controls,
whether
or
not
it
controls
where
go
looks
for
modules
when
it
can't
find
them,
and
there
are
a
few
options.
The
default.
B
If
it's
unset
is
to
go
talk
to
the
network
and
try
to
resolve
things
from
version
control,
but
you
can
explicitly
turn
it
off
and
if
you
turn
it
off
and
try
to
do
things
that
require
resolving
modules
and
it's
blocked
by
turning
network
access
off
the
operations
will
fail
so
to
demonstrate
that
let's
run
run
this
again
so
we're
running
and
we
had
already
downloaded
stuff.
So
this
ran
successfully
if
we
turn
Network
access
off
and
run
well,
we've
already
downloaded
things
into
the
cache,
so
we
don't
actually
need
network
access
anymore.
B
So
this
works
as
well,
but
if
we
empty
our
cache
and
then
try
to
do
the
same
thing,
so
we
don't
have
anything
cache
anymore
and
we
told
it.
You
may
not
talk
to
the
network,
but
we're
gonna
try
to
run
and
resolve
this
stuff
anyway.
Well
now
we
fail
it's
as
it
can't
look
up
the
module
because
we
cut
off
its
access
to
the
network
so
that
that
is
how
go
manages
cached
modules
by
default.
B
If
you
are
used
to
ven
during
all
your
dependencies
into
your
repo
and
checking
it
in,
you
can
still
do
that
as
well.
So
there's
actually
a
tool
built
into
code
now,
which
will
take
all
of
those
dependencies,
the
particular
versions
that
you
depend
on
and
put
them
into
the
vendor
door
inside
your
project,
so
that
is
really
nice
to
have
that
built
in.
Instead
of
having
to
use
some
some
third-party
tool
and
the
version
resolution
that
uses
matches
the
same
version,
resolution
used
by
every
other
go
tool
build
run
tests.
B
B
So
if
you,
even,
though
I
have
this
vendored,
if
I
did
that
experiment
again
and
turned
off
network
access
and
ran
without
a
cache,
it
would
still
fail.
You
have
to
explicitly
tell
it
to
use
the
vendor
directory
when
you're
in
module
mode.
This
is
all
doesn't
go
1:12,
so
we'll
see
if
that
changes
in
the
future,
so
I
have
no
module.
Cache
I
have
no
network
access,
but
I
have
told
go
to
use
my
vendor
directory,
even
though
I
am
using
modules
all
right.
B
B
B
The
versions
that
you
depend
on
your
transitive
dependencies
get
that
those
preferences
are
used
by
go
as
well,
so
go,
get
no
longer
just
automatically
grabs
master
of
everything.
There's
version
information
and
transitive
dependency
version
information
available
to
go,
which
is
great
all
right.
So
now
we've
got
this
module
pretty
simple:
let's
see
what
happens
when
we
try
to
do
some
more
interesting
things
with
with
version
requirements.
So,
let's,
let's
add
a
new
dependency,
so
I've
got
another
module.
B
That
I'm
going
to
add
and
gonna
record
that
I
intended
to
use
it,
and
if
we
look
at
what
got
recorded,
we
noticed
this
indirect
decoration.
What
that
means
is.
We
said
we
wanted
to
use
this,
but
we're
not
actually
using
it
yeah.
We
have
no
imports
that
use
it
and
so
go
tooling.
Throws
that
on
there
to
say,
like
you're
recorded,
you
want
to
use
this,
but
you
don't
seem
to
be
using
it
directly,
but
let's,
let's
actually
use
it
now.
So.
B
B
B
B
B
B
So
if
we
look
at
our
go
module,
the
version
of
C
that
we
are
requiring
has
been
bumped
up
from
102
1
1,
and
this
happened
silently
without
us
knowing
about
it,
which
is
super
annoying,
but
let's
figure
out
why
it
got
bumped
up
to
version
1
1
go
gives
us
tools
to
look
at
the
graph
of
dependencies.
If
we
run
go
mod
graph,
we
can
see
all
the
modules
that
are
involved
in
a
build
and
what
versions
they
require,
and
this
right
here
is
the
culprit.
B
So
this
new
thing
we
pulled
in
required
version,
1
1
of
module
C,
and
if
we,
you
know,
go
look
at
the
the
definition
for
that
module.
We
can
see
yep
right
there,
it's
requiring
version
1
1.
Oh
now,
maybe
it
had
no
particular
reason
for
requiring
1
1.
Oh,
maybe
that
just
happened
to
be
the
latest
the
current
version
when
they
wrote
this,
but
the
way
go
modules,
work.
Everything
involved
in
a
build,
expresses
a
preference
for
a
version
and
the
largest
or
the
newest
version
is
selected,
and
so
we
wanted
one
one.
B
B
The
the
intent
behind
that
is
to
avoid
misleading
require
statements
in
go
mod
files,
so
if
a
newer
version
would
actually
be
selected
by
go,
it
will,
whenever
it
builds
the
module
graph,
it
will
reflect
the
actual
versions
that
are
being
used
back
into
the
go
mod
file.
So,
on
the
one
hand,
that's
helpful,
you
don't
have
to
go
like
dig
through
a
bunch
of
stuff
to
figure
out
what
the
go
version
resolution
already
knows.
B
On
the
other
hand,
that's
kind
of
crazy
making
if
you're,
trying
to
actually
pin
things
down-
and
you
don't
like
things
shifting
out
from
under
you-
there's
a
really
great
issue
open
in
the
goin
repo
talks
about
the
number
of
side
effects
is
more
than
it
should
be,
which
is
zero
anyway.
Back
to
our
use.
We
really
don't
want
that.
We
behavior
right
like
this
is
this
is
no
good.
We
don't
want
for
death,
we
want
cake,
and
so
we
should
be
masters
of
our
own
destiny.
We
are
the
top
level
module.
B
We
are
defining
this
build.
We
should
be
able
to
force
one
100
to
be
used,
and
so
fortunately
go
modules.
Give
the
main
module
a
way
to
do
this,
and
that
is
with
a
replace
directive.
So
the
required
directive
says
I
want
a
version.
At
least
this
new
replace
directive.
Lets
you
say
no,
it
must
be
exactly
this
version,
and
so
there's
a
command
line
tool
called
go
mod
edit.
That
has
a
bunch
of
options.
One
of
the
things
that
lets
you
do
is
specify
these
replace
directives
and
the
structure.
B
When
you
want
to
pin
a
version,
you
say
which
module
you
want
to,
pin
which
module
you
want
to
use
and
what
version
and
when
we
run
that
that
shows
up
in
the
go
mod
file
like
this.
So
on
the
left
hand
side,
you
have
the
thing
you
want
to
replace
and
on
the
right
hand,
side
you
have
what
you
want
to
replace
it
with.
B
Now
all
the
normal
caveat
apply
here
like
if,
if
there
was
an
actual
incompatible
change
or
there
was
behavior
that
the
in
the
new
one,
one
no
version
that
was
depending
on
obviously
this-
this
wouldn't
work,
but
in
our
case
none
of
that
existed.
So
we
were
able
to
pin
to
a
version
and
not
break
ourselves.
B
So
a
couple
caveats
about
these
replaced
directives.
The
first
one
is
they
only
work
in
the
main
module.
So
if
you
are
running
the
build
for
command,
if
you
are
defining
the
main
package,
then
that's
great,
but
if
you
are
defining
something,
that's
intended
to
be
used
as
a
library
by
other
people.
Putting
replace
directives
in
your
go.
Mod
file
isn't
going
to
do
anything.
Those
will
be
ignored
when
your
library
gets
pulled
in
as
a
dependency
and
another
build,
so
be
aware
of
that.
B
B
Pinning
to
a
particular
version,
so
in
this
case
the
left-hand
side
and
right-hand
side
are
the
same.
All
we're
doing
is
for
singer
version.
Another
way
you
can
use
replace
directives
is
to
point
to
a
fork.
So
if
you
wanted
to
make
a
fork
of
something
and
then
make
some
changes
and
then
or
test
with
that,
you
can
actually
tell
it
finds
the
source
for
this
thing
here.
So
that's
that's
really
handy
you
might
have
to
rewrite
imports.
You
don't
have
to
do
anything
like
that.
B
It
tells
go
where
to
find
the
source
for
that
now.
The
thing
that's
located
at
this
location
must
actually
be
a
drop-in
replacement.
For
that
again,
no
import
rewriting
is
done
for
you,
so
it
must
be
source
compatible,
but
this
is
really
handy
for
testing
with
a
fork
dependency
and
the
last
thing
that
replaced
lets.
B
You
do
is
point
to
you,
a
local
path
on
disk,
so
the
left-hand
side
is
the
import
package
of
the
module
and
the
right-hand
side
is
an
actual
relative
path,
and
so,
if
you
were
wondering
like
how,
how
do
I
develop
multiple
modules?
At
the
same
time,
I
used
to
do
that
in
go
path,
and
now
it's
gonna
like
check
some
stuff
and
not
let
me
modify
it
well.
This
is
how
you
you
set
up
for
place,
directives
that
point
to
the
peer
folders
on
disk
as
you're
doing
your
local
development.
B
You
have
to
remember
not
to
commit
those
which
is
kind
of
annoying.
I
haven't
found
a
great
workflow
for
doing
this
in
a
non
temporary
way.
So
before
you
actually
commit
and
push
to
go
mod
file
up
to
source
for
other
people
to
pull
down,
you
would
want
to
drop
those
alright
so
to
wrap
up
what
about
major
version
compatibilities.
B
B
Give
you
a
way
to
do
this?
It's
not
as
magical
as
you
might
hope.
Basically,
if
you
make
an
incompatible
change,
you
also
need
to
change
the
import
paths
of
your
package
and
go
modules.
Do
this
with
an
affordance
that
signifies
like
a
major
version,
so
here's
an
example
of
an
incompatible
change.
We
wanted
to
make
to
this
signature
and
to
do
that
in
a
way
that
could
be
consumed
by
so
that
our
old
and
new
version
could
both
exist
side
by
side
in
a
build.
B
We
have
to
change
the
import
path
of
our
package
and
that
has
all
the
implications
all
the
ripple
effects
that
you
would
expect.
It
means
that
all
the
consumers
that
you
have
also
have
to
change
the
import
paths
that
they
use
to
import
your
package
and
so
switching
to
use
version.
2
of
this
module
would
look
like
changing,
which
version
you
required.
So
you
see
the
name
of
the
module,
actually
changes
along
with
the
version
and
then
all
the
import
paths
that
you
would
expect
to
refer
to
that
module
with
also
change.
B
Two
incompatible
versions
of
the
same
module
you
put,
the
same
module
in
scare
quotes
because
it's
actually
a
different
import
path.
It
allows
them
to
exist,
side-by-side
and
actually
compile
and
run.
And
if
we
look
at
the
graph,
we
now
depend
on
v1x
of
module.
C
and
D
now
depends
on
B
2
of
module
C
and
it's
using
functions
with
different
signatures
and
they
can
coexist
into
the
same
building.
So
a
couple
benefits
of
that
allow
side-by-side
use
of
different
major
versions.
B
What
an
interesting
thing
is
that
v2
of
the
module
could
actually
use
v1
of
the
module
if
it
wanted
to
so
a
module
can
import.
A
different
version
of
itself
gets
a
little
squirrely,
but
if
you
didn't
want
to
maintain
the
same
logic
in
a
lot
of
places,
you
could
do
that
if
you
wanted
to,
if
you're
looking
for
magic,
you're
gonna
be
disappointed,
there's
no
magic.
You
could
almost
do
the
same
thing
with
just
creating
a
v2
package.
B
B
B
Alright,
so
then,
just
a
kind
of
a
whirlwind
list
of
links
and
resources,
there's
a
lot
of
help.
Topics
in
the
go
command
itself
that
talk
about
modules
and
the
go
mod
file
and
the
mod
command
and
how
go
get
changes
to
be
module.
Aware,
there's
details
about
the
go
proxy
environment
variable
that
lets
you
point
to
a
folder
on
disk
or
disable
network
access
when
resolving
modules
and
there's
also
a
link
to
the
golang
wiki
and
then
finally,
just
a
bunch
of
kind
of
different
recipes.
B
If
you're
using
go
112,
which,
if
you're
developing
for
kubernetes,
you
must
be
at
this
point,
you
actually
have
to
opt
in
to
using
go
modules
and
go
113
they'll
be
on
by
default.
But
if
you
want
to
run
the
stuff
that
I
showed
here
need
to
opt
in
by
setting
this
environment
variable,
we
looked
at
how
to
create
initialize
a
new
module.
There
are
a
few
commands
that
lets.
You
see
the
module
graph
and
will
tell
you
why
a
particular
package
is
imported.
B
Before
you
commit
anything
that
uses
a
go
module,
you
should
run
go
mod
tidy
that
resolve
make
sure
everything
in
the
mod
file
can
be
resolved.
It
removes
things
that
aren't
used
formats
it
and
it
adds
a
checksum
file
so
that
when
you
download,
if
there's
a
disagreement
in
checksums
that
gets
flagged
by
they
go
to
this,
we
talked
about
how
the
go
tools
will
rewrite
your
go
mod
file
for
you.
If
that
drives,
you
crazy
and
you
don't
want
that
to
happen,
and
you
just
want
to
manipulate
the
go
mod
file.
B
B
You
can
also
dump
it
out
to
JSON.
If
you
want
to
manipulate
that
or
query
it
with
other
clues,
we
looked
at
commands
for
forcing
download
to
the
local
cache
and
cleaning
the
local
cache,
as
well
as
forbidding
network
access.
When
resolving
modules-
and
one
interesting
thing
is,
you
can
tell
it
to
look
at
a
particular
file
path
to
resolve
modules
and,
as
it
just
so
happens,
the
module
cache
that
go
maintains
is
in
the
right
format
to
support
that.
B
So,
if
you,
if
you
run,
go
mod
download,
then
your
module
cache
will
be
populated
with
all
the
requirements
for
your
current
module
and
you
can
point
to
go
proxy
at
that
path
and
any
resolution
that
has
to
be
done
can
do
so
against
the
module
cache
cache,
which
is
kind
of
cool.
You
can
also
point
it
at
a
network
location,
but
that's
more
complicated
and
there's
a
health
topic
to
find
out
more
about
that.
B
B
B
A
Yes,
you
could,
but
you
shouldn't,
because
there's
currently
no
way
for
you
to
like,
if
you're,
developing
and
you're
developing
a
dependency
and
a
thing
that
uses
the
dependency
at
the
same
time,
there's
like
no
way
to
get
them
to
talk
to
there's
no
way
to
get
it
to
use
the
thing
that
you're
developing,
except
by
using
this
local
rewrite.
So
if
we
use
it
internally
to
implement
things,
then
people
have
no
tools
to
yeah.
B
A
B
A
man
you
would
run,
go
mod
vendor
and
then
commit
the
vendor
directory.
Okay,
yeah.
It
really
has
to
do
with
where
the
we're
the
modules
live
like.
If
you
want
them
to
live
like
somewhere
else,
either
cached
or
resolved
by
a
proxy
that
you
control
or
whatever,
then
you
would
use
the
go
proxy
stuff.
If
you
want
them
committed
in
a
vendor
directory
than
you
would
use,
come
up
them
got
it.
D
B
I'm
most
familiar
with
tags,
I
think,
if
you
specify,
if
you
specify
a
branch
name
go,
will
actually
resolve
that
to
the
head
sha
of
that
branch.
The
next
time
it
looks
at
the
module
graph,
and
so
you
can't
track
a
branch.
The
way
you
would
want
to
you
could
say,
like
I,
want
master
of
this
or
I
want
release
1/3
of
this,
but
the
next
time
you
run
a
command
like
go
test
or
go
build.
It's
actually
going
to
resolve
that
to
a
shop
and
lock
you
to
that
shop.