How can I overcome Golang's requirement that every package have buildable code in it? - go

I am building a web application in Go and as part of it I have several middelware functions defined. Right now they all live in "my/middleware" package. That namespace is becoming very cluttered by all the different functions I've defined so I decided to put them all in their own subdirectories, e.g. "my/middleware/gzip". When I do this I get the error:
no buildable Go source files my/middleware
I don't want all of these functions in the same namespace, but it seems my only option is to create a placeholder .go file in the my/middleware directory with an empty init function or something. That sounds terrible so I'd like suggestions on how to achieve my goal to group a similar class of packages when there isn't any shared/common code to live in the parent package.

You are actually taking the right decision by splitting the files into different subfolders. It is not different than what is done here
https://golang.org/pkg/compress/
This allows for the clients of your framework to take only what they need. The idea is to avoid dependency bloating. Go is all about being lean.
The error you receive is because you try to build a package that doesn't exist. Think of that folder as a logical grouping mechanism, you need to build the packages given by the child folders individually.

Related

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.

Splitting a single package/module into multiple (many) files gives undefined error on go build ./

I like splitting my modules/packages into many files (e.g. a bigger function file and a coupled helpers file). Now a module can have many bigger functions as it grows. Let's say my modules/packages each consist of around 30 files.
When I started working with Go a few days ago, I was a bit confused about the module pattern. I have a JavaScript (ES6+) background. After some research, I found you could build packages consisting of multiple files by running the following command go build ./.... This worked out pretty well, until my package consisted of about 10 files. All of a sudden I saw errors about functions being undefined. Meanwhile those functions where clearly defined in the src of the module/package (and properly capitalized).
My gut feeling says that this is because of the build order. Say we have 2 files 'a.go' and 'b.go'. file 'a.go' got a reference to a function in file 'b.go'. When file 'a.go' is build before 'b.go', an undefined error appears. My second gut feeling is that file 'a.go' contains a reference to a function inside file 'b.go' and the same vice-versa. So file 'b.go' also has reference to a function in file 'a.go'.
Is my first of my second gut feeling correct?
How do people commonly tackle this problem, or even better, what is the best practice?
What is the proper way creating a single module which consists out of many files?
You can have as many .go files in a single directory as you'd like.
A Go package consists of all of the .go files in a single directory. Each .go file in a single directory should have the same package foo declaration as the other .go files in the same directory.
Your source code imports code from another package (another directory) via an import path supplied in an import statement such as import "github.com/my/repo/pkg1".
To build a package, you can cd to the directory and issue go build . (where . means build all the files in the current directory, or you can also just issue go build in that directory without any arguments because the default is .).
Code within the same package (the same directory) can reference code in other files in the same package (same directory) without needing to import the other files, and without needing the symbols to be exported (uppercase first character).
It is well worth the time to read "How to Write Go Code", which includes an overview of these concepts, including:
Go programmers typically keep all their Go code in a single workspace.
A workspace contains many version control repositories (managed by Git, for example).
Each repository contains one or more packages.
Each package consists of one or more Go source files in a single directory.
The path to a package's directory determines its import path.
and a bit later it describes the relationship between "workspace" and GOPATH:
The GOPATH environment variable specifies the location of your workspace. It defaults to a directory named go inside your home directory, so $HOME/go on Unix, $home/go on Plan 9, and %USERPROFILE%\go (usually C:\Users\YourName\go) on Windows.
Regarding your more specific concerns:
Splitting a single package into multiple (many) files gives undefined error on go build ./
Splitting a package across multiple individual .go files in the same directory (same package) should not cause a problem in and of itself, but of course it needs to be done properly (e.g., all .go files in the same directory (same package) need to have the same package foo declaration near the top; files in the same directory should not attempt to use import statements to import other files in the same directory; etc.).
My gut feeling says that this is because of the build order.
Build order shouldn't matter here.
My second gut feeling is that file 'a.go' contains a reference to a function inside file 'b.go' and the same vice-versa. So file 'b.go' also has reference to a function in file 'a.go'.
This is fine if a.go and b.go are in the same package (the same directory).
On the other hand, this is not allowed if a.go and b.go are in the different packages (different directories). This is because Go does not allow circular dependencies at the package level. If this is the problem, the simplest solution is to move a.go and b.go into the same directory, or refactor to introduce a third package to break the cycle so that a and b can both depend on the third package, or use interfaces, or other possible solutions, but given you say you are new to Go, the simplest solution might be best while you are learning.

Project structure for a tool with multiple UIs

I'm playing with golang and made a tool for password generation. Initially it was intended to be used as a command line tool. I later separated the generation logic into a separate package (still same github repository) and left the main function in the root of the project. Now I also want to add a simple web frontend (nothing fancy), but I don't know how to structure the packages.
Am I supposed to put both the command line entry point as well as the web UI into their own packages in the same project (which leaves the root empty). Or maybe I should move the actual generation library to the root and the UIs in separate packages. I guess the other option is to have the UIs in separate projects on github, but they are only going to be used for this library, so it does not seem like a good idea.
I remember seeing in some projects packages named cmd for example, but never have I encountered one, with multiple front ends. Is there a go(-gettable-)way for doing this?
I agree that there's not much point in making separate projects/repositories if they're only going to be used for this library. I would just have a cmd directory with a subdirectory for each executable you're building.
Something like this:
github.com/user/project
generation
cmd
cmdline
main.go
web
main.go
The main.go files can use the functionality that you've broken out into your "generation" package.
The name of the executables produced by go build will be the name of the parent directory, so cmdline and web in this example (you would want to choose better names).
Note: you don't actually have a package cmdline or web. The files in those directories would all be in [their own separate] package main.

Working with digital signatures in Go

I would like to use signatures for a program that I am writing in Go, but I can't figure out the documentation, which is here. In particular, I would like to use the SignPKCS1v15 and VerifyPKCS1v15 functions, but I'm not sure exactly what I have to pass as arguments. I would greatly benefit from some example code of these two functions. Thanks.
Note: The message that I would like to send is a struct that I defined.
I think the src\pkg\crypto\rsa\pkcs1v15_test.go file in the Go source tree should be a good start.
An update striving provide more context… Go source contains many tests for the code in its standard library (and the crypto/rsa package is a part of it), so whenever you have no idea how to use a standard package (or, actually, any other Go package), a good place to start is to look at the tests involving that package as testing code naturally uses the package! Tests are kept in files ending in _test.go, usually have meaningful names and are located in the same directories actual code implementing a particular package is kept.
So in your particular case you could do this:
Download the Go source package of the version matching your compiler (what go version shows) and unpack it somewhere.
Navigate to the directory matching the package of interest. Code for standard Go packages is located in the "pkg" directory under the "src" top-level directory, so if you're interested in the crypto/rsa package, you need the src/pkg/crypto/rsa directory.

refactoring modular structures in D

Here's how I usually develop an application:
I start with having all the code in a single source file.
When it grows enough to be modularised, I break the code into several modules.
When the modules grow enough, I split them again. And so on, iteratively.
Over time, some modules get shrunk, deleted or merged with others.
This workflow implies the need to move source files between modules sometimes. And here comes the problem:
When I move a module to another location, it changes the module's name, so I have to walk through all the other files renaming imports by hand.
Is there some organisational technique to avoid that annoying procedure? Or is that the way it goes and I just have to look into some automation utilities instead?
you can create a *.all module that public imports all modules in the package
then you only need to add/remove the module names from that module
You can override module name via module packagename.modulename; directive in the beginning of the module. It will need a help from the build system though as rdmd uses module names from import statements to form file system path to search for their sources. But if you will supply all source files project consists from by hand, it should resolve module names just fine.
It's better to define your entities before you start coding. You can use some modelling language to identify and write your entities. For example if you are using java to code your application then you can use UML to model this application.
Also, you have to separate buisness logic from data.
If you continue to do it like today you will lose a lot of time just dealing with filenames.

Resources