Setting package path in Go - go

Getting started with Go and going through the docs here: https://golang.org/doc/code.html
The part entitled Package paths recommends using my Github account as a base path. However, with the forward slashes in the GH url, when I run mkdir -p $GOPATH/src/github.com/user it creates a sub-folder. So the example of github.com/user creates:
src/
github.com/
user/
but I don't think this is what's intended.
What can I do here?

The behavior is correct. The packages names in Go provide unique global name space.
github.com/user/repo therefore identifies a package, which is easily go get -able (download and install the package) and also provides much needed separation. You can also create packages without a hostname (in this case github.com) but effectively preventing users from using go get and resorting to manual management.
Having a username in GitHub case allows you to use forks of other libraries and maintain the separation. The full package name is then used for importing
import "github.com/user/repo"

This is actually the intended behavior,
You can even call go get on a github repo and it will create this same directory structure

Related

What is the correct setting for GOPATH?

I was trying to follow a tutorial on using aws with go. When I gave the command "go get github.com/aws/aws-sdk-go/aws", I still got failure to import. I was left wondering if the "go get" succeeded or not.
Following the guidance provided in the answers here, I updated my GOPATH variable and now the import succeeds.
Your hello.go should start something like this:
package main
import (
"github.com/aws/aws-sdk-go/aws"
)
See this example in the playground. So when importing a remote module use the full path in the import statement.
Re another question you asked in the comments (and I mentioned in comments to another of your questions) - go mod init initialises a module. See this article for information. When using modules, GOPATH is no longer used for resolving imports (see this article). So basically GOPATHis the old way of doing things; go modules is the new way (it solves a lot of issues but having the two approaches can be confusing to someone new to the language because some tutorials assume GOPATH and others use modules).
For completeness you have other questions about environmental variables. I think this may be due to a misunderstanding about how these work. When you enter export GOPATH=XXX in a terminal session that will update the environment within that session (that is that terminal window only; it will not have any impact on any other sessions you have open, including vscode). If you want to set a system wide environmental variable then you need to update a configuration file (often ~/.bashrc but this depends upon your OS see this article for info). After doing that restart the applications (or ideally youre PC) to pick up the new setting.
When you run go get github.com/aws/aws-sdk-go/aws; go tool will download the package into $GOPATH/src/github.com/aws/aws-sdk-go/aws directory.
That is why you need to import package by its full name (which is same as path to files under $GOPATH/src directory:
import "github.com/aws/aws-sdk-go/aws"
You can find more about how source code is organized under GOPATH and how imports work here and specifically about remote (github) imports here.
NOTE: GOPATH resolution works only when your project doesn't use modules (you don't have go.mod file). If you're following a tutorial and it doesn't mention use of modules above should work fine.

Multiple files in same package in Go

I'm writing my first Go code which among other things, sends an email. After finding out that the package net/smtp only supports Plain Auth (but some providers like outlook doesn't support it), I asked for a solution and got pointed out to https://gist.github.com/andelf/5118732.
That code works like a charm, but as it's not something written by myself, I would like to add it in a separate file and just reference it in my main.go.
What's the right approach to have multiple files in the same package? I don't want to create a different package just for that code, first because it's not mine, and secondly, because I think it's an "overkill" approach, isn't it?
I thought that as long as the files are in the same directory, I could have many *.go files, but it seems it's not working out. If I just create a file with the content of that gist, the compiler fails because expected package, found import. If I add something like package auth, then it fails because found packages auth (auth.go) and main (main.go)
So, what's the general practice in this situations? Just create packages for everything?
You can have only one package in a directory, and it looks like you don't need a package for this addition, so you can simply put that in a separate file, and add package main at the top. Having a main package and putting everything under it works up to a point. As things get larger, you have to break it up into self-contained packages.
If your current working directory is in GOPATH, then you can just add new go file with same package name main.
If your current working directory is not in GOPATH, you can still put them in multiple go files and when you run the program, you should use go run *.go instead of just go run main.go.
There are also other options which you can refer Run code with multiple files in the same main package in GoLang for detail.

Implications of not using repo path for my own packages

Suppose I decide to keep all personally developed packages organized
as follows:
$GOPATH/
bin/
pkg/
src/
somepkg1
somepkg2
...
somepkgN
Further, suppose there is a great deal of code reuse among them, so I
decide to keep the whole $GOPATH workspace under the same Git
repository (each package could be a submodule), as opposed to more
traditional scenario where subpackages are less coherent (co-existing
solely because of using go get from the same workspace):
$GOPATH/
bin/
pkg/
src/github.com/<me>/
somepkg1
somepkg2
...
somepkgN
I can see that with the former approach (not using github.com/<me>/
in the package paths), go get would not be able to fetch packages as
they are not "declaring" themselves to be available online. However,
one can easily work around that by using git submodules, so all
packages would be fetched in the first place (note it's a tightly
controlled ecosystem so there will be no name clashes).
Is there any other limitation (besides go get) of not using full
paths for packages?
(I am mostly concerned about limitations arising from certain code
refactoring/analysis tools that exploit the repository path as base path convention that
allows go get to look for the package online.)
For the Go compiler and all elements of the go tool except go get the package import path is an almost opaque string containing the import path. You can lay out your code like you want (the compiler itself happy compiles files from different folders into one package). If you don't need or want your code to be go getable there is no need to use a repo path. The analysis and refactoring tools in golang.org/x/tools work on the opaque import paths (as far as I know) and do not access the network.

go get with multiple projects in workspace

In Go, the workspace contains the src, pkg and bin directories. How do I create multiple projects in the workspace, each with its own src, pkg, bin directories, such that I can 'go get' packages into the pkg directory of a particular project.
You probably do not need that. Let's forget also the word "workspace" it's probably only confusing you.
If you set your GOPATH environment variable that that's all you actually need to have multiple projects independently sitting on you hard disk.
For example, having export GOPATH="$HOME", and performing
$ go get github.com/foo/bar
$ go get github.com/baz/qux
Your directory tree will be
$GOPATH/pkg...
compiled packages
$GOPATH/src/github.com/foo/bar
bar.go
$GOPATH/src/github.com/baz/qux
qux.go
More details here. Note that it does talk about workspaces, but I still consider that fact very unfortunate. The earlier versions of that doc did not use nor define the concept and they were useful anyway. That's IMO a proof of it (the workspace) being redundant.
go get is not intended to be used that way.
all go get packages land in $GOPATH/* as described here: http://golang.org/doc/code.html#remote and there is no concept of separate workspaces.
If you really want several "workspaces": Have several entries in GOPATH (separated by ":" on unix).
(But most just keep everything under one GOPATH).
Remember that go get fetches packages only into your first GOPATH entry.
The other entries can be used as "seperate workspaces".

Easy way to change .deb build prefix?

I am trying to make a live CD for simplifying chrooting into unbootable Linux systems for users, as many unbootable Linux issues could be fixed with chroot, but many users probably don't understand the concept of chroot.
One of the abilities I want to add is the ability to temporarily import some utilities from the Live CD into the target system, so that they can be used as if they where installed, to do configuration tasks.
The problem is is that I can't seem to work around the apps trying to search for stuff in /usr/share when they are imported. (I already have a hacky workaround for /usr/lib using patchelf...) I would do a union mount on the /usr/share's, but that could confuse some package managers when they see files that should not be there, as the user might need to run a package manager to fix the broken system. (or at least I think it could confuse package managers).
I'm trying to see if I can create a script that will rebuild all packages to use a different build prefix instead of /usr. The script can rebuild packages with apt-get build-dep/apt-get source/debbuild, but it can't change the prefix.
Question: Is there a way to pass an argument to debuild or dpkg-buildpackage to change the build prefix?
Right now it seems I have to take a look at the contents of the source (from apt-get source) for every package and see what files are specifying /usr and figure out a way to change it for every one, but I have a feeling I'm missing something obvious...
Is this possible?
I don't think this is feasible. Why don't you mount in a different location, for example /usr/local? That way, you also eliminate a source for possible conflicts.
Still, some packages are full of hardcoded references to the location for their data files, for example.
I'll throw in a pointer to stow as well, although I imagine it's not really helpful for your scenario.

Resources