Go, using other packages in the same project - go

I have the following situation, where I can't use romanNumerals in romanserver, inside a folder in my module directory.
go run romanserver/main.go
romanserver/main.go:13:2: no required module provides package github.com/BuddhiLW/roman/romanNumerals; to add it:
go get github.com/BuddhiLW/roman/romanNumerals
I want to upload the roman project to GitHub containing both romanNumerals and romanserver. Of course, I would like to export variables from one another.
I'm still confused about how that is done in Go.
EDIT: I deleted go.mod in both romanNumerals and romanserver, and now everything is working, just like
Cerise Limón pointed out.

Related

Go Modules vs Package

just starting to learn about Go Modules. I have a question on importing local packages inside the same module. The example I am looking at is this repo:
https://github.com/Azure/azure-service-bus-go
The module is module github.com/Azure/azure-service-bus-go. There is a separate package inside that module, atom (but it's not a module itself).
When files inside the main package import atom, they do it like this: import "github.com/Azure/azure-service-bus-go/atom" -- see queue_manager.go as an example.
What I do not quite understand -- how does GO know to look at the local atom package, as opposed to, say the one on Github? It seems confusing to me that something that is part of the module being modified is referenced by a remote/absolute URI. Is it guaranteed that if I modify the file on local disk and build I'm actually referencing the latest version as opposed to something already pushed?
As a toy exercise I tried to create a module with a non-existent Github URI and it did in fact appear that go mod tidy tried to look that up against Github, even though a local copy did in fact exist
A module is a collection of go packages.
A package is a directory of .go files. Using packages, you organize your
code into reusable units.
We can add a module to go project or upgrade the module version.
The module directive in the go.mod file declares the import-path prefix for all of the packages within that module.
If you are just starting to learn about Go modules, the
Create a Go module tutorial might be a good place to start.

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.

What is the best local structure for Go open source repository development?

I'm trying to debug Go implementation of ethereum(link), because my core interest is in developing new consensus algorithm (i.e. modify the open source Go code from github).
However, I'm having problem with the location/path of the source code. When I put the folder(i.e. go-ethereum) outside of the $GOPATH and then try to compile&debug geth(go-ethereum/cmd/geth/main.go) it shows the following error: Use of internal package is not allowed.
From that error message, I figured out that the import github.com/ethereum/go-ethereum was not importing my source, and instead it was getting code from internet(like other libraries). Which of course is definitely what I shouldn't do when I'm trying to modify the github.com/ethereum/go-ethereum package code.
So, my workaround was to clone the source code into $GOPATH/src/github.com/ethereum/go-ethereum and followed this answer, and Goland IDE started compiling&debugging without error (wasn't able to go build ./cmd/geth/main.go though due to error undefined: configFileFlag...)
Thereby now I've got a working debugger that can debug with my source code modification, but this doesn't look like ideal source code structure.
The question is:
Is putting source code inside $GOPATH(because of internals) a proper approach? If so, what if I was using go-ethereum package from another project?(Fortunately I'm not, but I'm curious) Do I have to stash&revert changes I made to the code?
Yes, the folder structure you ended up with is the right one.
Code should be under $GOPATH/src as you describe.
But note that $GOPATH is not a fixed folder in your system, you can have multiple projects under different folders and change the value of $GOPATH accordingly depending what you are working on (or have multiple console terminals open, each with its own $GOPATH value).

What is the reason to have GOPATH set to my workspace?

I read everywhere that my GOPATH must be set to my workspace. If I do that and use go get to get packages from for example GitHub, they are all added to my workspace though, which I don't find particularly useful because it clutters my workspace. In my workspace I expect to find MY code and my code only.
So I now have my own repos in ~/repos/go and left my GOPATH to be the default ~/go. This works perfect. All libraries I import live in ~/go, which keeps my own workplace ~/repos/go nice and clean. This works great for me, so I'm not sure why this is not the recommended way of working.
Am I missing something? Are there things I break or are functionalities not working in this way?
Edit
To explain why my question is different from this question: I know what GOPATH does (define a place to put packages when using go get and a place to import packages from), but I was unaware of why you need to have the public code in the same place as your own code. Turns out there is no need for it, as explained by #peterSO in the (excellent) answer I accepted below.
go help gopath
Go searches each directory listed in GOPATH to find source code, but
new packages are always downloaded into the first directory in the
list.
$GOPATH is a directory list. For example, on Linux,
export GOPATH=$HOME/gopublic:$HOME/goprivate
go get places all downloads in the first directory in the list: $HOME/gopublic. Put all your packages in the second directory in the list: $HOME/goprivate.
GOPATH is a default directory that the golang toolchain looks at when you're attempting to compile code. It's not technically 100% necessary to set a custom one, as if I recall correctly, it defaults to ~/go/.
As peterSO said above, GOPATH is a list and puts packages into the first entry.

How should I structure a simple Go project?

I have a pretty simple Go project that I'm trying to restructure so that it follows the normal Go project structure (and so I can run go build).
I currently have two source files, both with package main. All the files, including a few text configuration files that my program needs at runtime.
So right now, it looks like:
<project_name>
- main.go
- source2.go
- config_file.txt
I can run go build when I'm in this directory, and it creates one binary (named <project_name>. This works fine, but I'd like to set this up to better follow the Go standard package structure (specifically so that Intellij IDEA will recognize it as a valid project).
Right now, I have the entire <project_name> directory in Git, and I'd like to keep it that way.
I tried putting the source files in a folder called src, but then go build says there aren't any source files to compile.
How should I structure this?
EDIT:
Figured out the issue with putting stuff in src/: I need to run go build <project_name>.
I'm still wondering if there's a way to set up a project without a global GOPATH. I have all my projects under one folder, with a subfolder for each project (not all the projects are Go project). I'd like to keep that system.
What I want is:
projects/
- project 1/
- src/
- bin/
- pkg/
- project 2/
- src/
- bin/
- pkg/
Then I'd like to be able to run go build <project_name> (while I'm in that project's directory) and have it compile that project. Is that possible?
The "canonical" way to organize your Go code is described in How to Write Go Code. It is explained in a less formal way in this blog post. This concept is kind of contrary to what you have in mind - you have a workspace directory, specified by the GOPATH environment variable, and the source code of all projects resides in subdirectories of the "src" directory of the workspace. You can have multiple workspaces if you specify several directories in GOPATH.
I would suggest you give the "recommended" way to organize your code a chance, maybe it will grow on you. It may seem a bit unusual, but it has its advantages. If you find out you absolutely can't live with it, you can still work around it, e.g. by setting GOPATH dinamically in a script.
As for the Golang IDEA plugin, the last version I tried some time ago didn't yet support this project structure, but newer versions may have changed that. In fact, one of the plugin's authors (dlsniper) has added a comment to the above blog post giving examples of alternative project structures that still use a global GOPATH.

Resources