localpackage is a projcet to test local package reference problem.
THE PROBLEM The Discussion
My project path is: github.com/vipally/localpackage/problem/withlocal
The local package reference relation is:
withlocal <- withlocal/local
In "main" use such to reference local package local:
import "github.com/VIPALLY/localpackage/problem/withlocal/local"
Someone who forked this projcet as "github.com/someone/localpackage".
But how can his project working by avoid following change?
import "import "github.com/SOMEONE/localpackage/problem/withlocal/local"
The Solution Reference
Use local-reference-style [import "#/x/y/z"] to related to LocalRoot instead of GoPath.
Here are two examples of "hello world" main packages:
<ProjectRoot>/problem/withoutlocal
<ProjectRoot>/problem/withlocal <- github.com/vipally/localpackage/problem/local
"withoutlocal" works well anywhere <ProjectRoot> is, even out of GoPath.
"withlocal" works only when "<ProjectRoot> = <GoPath>/github.com/vipally/localpackage"
How does go team think about this difference?
It makes "withlocal" packages non-independent due to reference "LOCAL" packages as "GLOBAL" style.
If I want my package works well anywhere, I have to write everything in one single "HUGE-package".
Just like: all.Printf/all.OpenFile/all.GOROOT/...
Does this go team recommended?
We must explicit followed priority of go dependency package find process:
<ProjectRoot>: with highest-priorty path to find local packages.
<Vendor> : with second-priorty path to find explicit-version of local-referenced the third-party packages.
<GoRoot> : with third-priorty path to find standard packages.
<GoPath> : with lowest-priorty path to find third-party packages.
Think about that not every go-project is wrote for open-source(aim to share with others).
Thousands of private go-projects(eg:game-servers) focus on their own particular logic-flow only
and never shared private-packages at all.
We just called these projects "independent-projects".
Because they have hundreds-of private-packages but no one is wrote for share.
That is to say, they never care "where I am", but "what I need".
Unfortunately, these kind of projects are always "huge".
Maybe millions-of lines or thousands-of private-packages reference inside?
In this case, change project name or source control server become heavy work,
because the working path changes and thousands-of private-packages reference code have to be update.
But if local-packages are referenced by "#/modules/module1" style,
everything is change the name of project root only then.
How do you think about the difference between such styles of referencing local-packages then?
"#/modules/module1"
(<GoPath>/) "server/user/project/modules/module1"
"<ProjectRoot>/problem/withoutlocal" is a main package without any local package reference
It works well anywhere <ProjectRoot> is, even out of GoPath.
Hello World!
WITHOUT local import
Gopath is : E:/gocode/src
ProjectRoot is : E:/gocode/src/github.com/vipally/localpackage
ThisPackagePath: E:/gocode/src/github.com/vipally/localpackage/problem/withoutlocal
ReleatGopath is: github.com/vipally/localpackage/problem/withoutlocal
Hello World!
WITHOUT local import
Gopath is : E:/gocode/src
ProjectRoot is : E:/localpackage
ThisPackagePath: E:/localpackage/problem/withoutlocal
ReleatGopath is: ../../localpackage/problem/withoutlocal
"<ProjectRoot>/withoutlocal" is a hello world package with local package reference:
github.com/vipally/localpackage/local
It works only when "<ProjectRoot> = <GoPath>/github.com/vipally/localpackage"
Hello World!
WITH local import: github.com/vipally/localpackage/local
Gopath is : E:/gocode/src
ProjectRoot is : E:/gocode/src/github.com/vipally/localpackage
ThisPackagePath: E:/gocode/src/github.com/vipally/localpackage/problem/withlocal
ReleatGopath is: github.com/vipally/localpackage/problem/withlocal
withlocal.go:6:2: cannot find package "github.com/vipally/localpackage/problem/local" in any of:
C:\Go\src\github.com\vipally\localpackage\problem\local (from $GOROOT)
E:\gocode\src\github.com\vipally\localpackage\problem\local (from $GOPATH)
Maybe one solution Reference
LocalRoot is a <root> directory that contains such patten of sub-tree "<root>/src/vendor/" up from current path.
A LocalRoot has the same tree structure with GoPath and GoRoot.
Actually, a LocalRoot is a private GoPath that is accessible to sub-packages only.
This is the minimal state of a valid LocalRoot:
LocalRoot
│
└─src
├─vendor
│ ...
└─...
After build and install, it may become as:
LocalRoot
│
├─bin
│ ...
├─pkg
│ └─windows_amd64
│ └─...
└─src
│ ...
├─vendor
│ └─...
└─...
import "#/x/y/z"
Which means [import "x/y/z"] from LocalRoot, and never search from GoPath/GoRoot.