Hi

I think one of the main struggles stems from "dependency" having two
technical meanings:
 a) If a package a imports a package b then a depends on b.
     This is a priori agnostic to versions.
     This type of dependency is expressed by a simple import 
"import/path/of/b"
     in a's source code.
 b) Some set of packages might depend on an other set of packages
     in a specific version.
     This is expressed by a require directive in a go.mod file.
Do not conflate these two.

One more point to takeaway: A module is a set of packages which are
developed together and released together with a single version number.


On Wednesday, 23 October 2019 21:09:51 UTC+2, Stuart Davies wrote:

> Ok this is my current understanding. Please correct me if I am wrong.
>
> 1) The main purpose of a go.mod file is to indicate where the dependencies 
> are and their version number.
>  
>
Not exactly. There are two main purposes:
 - Specify the name of the module. As the name of the module is kinda
   prefix of all package import path living in this module this a _very_ 
important
   thing and must be done properly (especially for version >= 2.0.0 of a 
module).
 - List the direct and indirect dependencies and their (minimal) version.
Dependencies in a go.mod are modules. A module is a set of packages
with a common version (versioned together). Packages  are identified by 
their
import path.
The "where the dependencies are" is secondary. The "wehere" can be changed
by a replace directive. 
 

> 2) In my small project the 'module' is 'where the go.mod file is' (root of 
> webserver).
>
You project is badly organized or I missread your last post.
The best advice is: Stop trying to get fancy until you feel comfortable
working with modules. So please: Put the go.mod in the toplevel
dir of your git repo an have just one go.mod file and thus just one
module. (It is perfectly fine to have tens of module in a git repo but
such a setup is *not helpful* while trying to understand the basics.)
 

>
> 3) A module contains packages in sub dirs (these are what we import). 
>     a) If it has no packages in sub dirs is it still a module?
>
No really. This is just plain nonsense. The right way to think of modules
is: A module groups packages. A module without packages is nothing
sensible. A set of packages versioned together is a module.

    b) Import dependencies between packages in a module must use the full 
> module path and the package name
>
No. What you state here is not really wrong, it just is not right either.
It is kinda the other way around. The main concept is: Packages are
identifed by their import path. Package path lookup works by finding
the module and the package inside the module. If you have a package
in subdirectory foo/bar of your module xyz/wuz then its import path
is xyz/wuz/foo/bar.
(The package name is what you call the package in its first line in the
source code with the "package name" declaration
and this is of no concern for dependencies or importing packages).


    c) There should be no main() in a module
>
No. 100% false. You can have a lots of package main in a singel
module. Remember: "A module is a group of packages versioned
together." Whether these packages are "libraries" or "program"
does not matter at all. 

4) The directory 'example' is a module (it has a go.mod) file.
>
Yes
 

>     a) It has NO packages of it's own.
>
Wrong. It contains a file webserver.go and this is the
package making up this module. 

    b) It has a dependency on the 'webserver' module which must have a 
> go.mod file (as it does).
>
Well, true, but nonsensical.
 

>     c) The purpose of the 'example' mod file is to locate the module 
> dependencies (not the packages)
>
There is no purpose for a go.mod file in the example directory except.
Really. This is complete nonsense.
 

>     d) Strictly speaking this is NOT a module (nothing will depend on it) 
> so I should either move it outside the module or get go mod to ignore it by 
> prefixing with '_'
>
Whether something depend on something has no influence on being a
module. A module is a group of packages versioned together. Nothing
less but especially nothing more.
Go code depends on packages (that's what you import). Packages which
work together and are versioned are grouped in a module. A module
has a version 

    e) It is where the main() is.
>
Location of package main and func main() has literally nothing to do
with modules.
 

>     f) Is there any reason it could not be a module and be a dependent of 
> another module?
>
If have no idea what you mean here.
Best advice: Stop going micro-module.
Technically each and every of your packages you ever develop
could live in its own module. But this is nonsense in real life
where you develop a program, a set of programs working togther
or a set of library packages working together and this "together"
is tested, versioned and released together under one version number.
 

>
> Modules are normally stored in git (or equivilant) but even if they are 
> not they need a module name that includes the git path and a go.mod file.
>
Technically no. Now you enter a different real here: How to
find the source code of a module. Formally you could name
your module x whatever you like, store it on disk wherever you like
and add a replace directive to each module which import a package
from x pointing to that disk location.
So basically a "Yes!" on this. Your module are named
    github.com/<youraccount>/<repo>
 

>
> My 'webserver' go.mod file was created with the name:
>     github.com/mygit/webserver
>
> My 'example' was created with the name:
>     github.com/mygit/webserver/example
>     
> I have a sneeking feeling that if outside of 'webserver' it would be:
>     github.com/mygit/example
> Could it be:
>     github.com/mygit/webserver/example
> Or if renamed:
>     github.com/mygit/webserver/_example
>
I do not understand your structure well enough to comment on this.
 

> I am really not sure what the correct name is here. If not a dependency, 
> does it matter?
>
Probably you are conflating import dependency and version dependency.

On any case: Yes the module name *does* matter!
If you have a 
    module foo/bar/xyz
then the import path of each and every package in this module
start with foo/bar/xyz, e.g. foo/bar/xyz/wuz/kik for a package
in wuz/kik.
 

>
>
> *Now for 'replace' this is where I get a bit vague.*
> Replace, changes a module's dependency path. Either changing the version 
> number or the actual modules full path. E.g. => 
> github.com/someothergit/webserver.
>
Not really. It can change the version and/or where to find it.
There simply is no "module path". A module has a name
specified with the module directive in the go.mod. This name
cannot be changed with a replace directive.
 

>
> Replace can change a modules path to a local directory path.
>
Correct if you thing of "module path" as "where to find the module".
 

>
> a) A local path of ./ indicates that the dependency (module) is in the 
> same 'module' (as with example currently)
>
Maybe. This is useless and never needed.
 

>
> b) A Local path of ../ indicates that the dependency (module) is one level 
> up. 
>     Is this in the same module or one levelup from the go.mod file?
>
Even more strange here. No specifiying that the source of a module lifes
one level up in the file system directory structure is plain nonsense. 

>
> c) A Local path of ../foo indicates that the dependency (module) is one 
> level up in the directory called 'foo'.
>     In my case if 'foo' contained 'webserver' would the path be:
>     ../foo/webserver
>     Or
>     ../foo
>
Maybe. At least this is no longer nonsensical.
Stop going clever with ../ and use an absolute path, with this you
will understand what is going on. Such a replace directive tell Go
where on disk to find the source code of that module. Thats all
to know.
 
Again: The best advice is: Use *one* go.mod at the source of your git repo
and treat everything in there as one module. This is perfectly fine for
your repo: You want to version your example and your server together!
Nobody ever will want your webserver code in version 1.2.3 but your
example in version 3.4.5!

Are there any diagnostics for dependency resolution.
>
> Is there anyway of logging what the actual resultant 'replace' finds (or 
> not). It seems to fallback, ignoring the replace, if it cannot be found. 
> This would be really informative.
>
I doubt it fallback.
The problems in your code stems from not treating a set of
packages versioned together as a single module.
Your could would not need any replace directive.

V. 

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/b0dc887a-a8d6-451b-918e-643fa0e74b47%40googlegroups.com.

Reply via email to