Export structure only for testing in Golang - go

I have a utility package that many other packages use. I also created some test structures that implement those interfaces. And I put them in interfaces_test.go
I'd like to be able to import those test structures in other packages in my *_test.go files.
I saw something like that in http://golang.org/src/pkg/os/export_test.go but whatever I try I get an error similar to this one:
go test something/mypackage
mypackage/ant_lat_lon_test.go:46: undefined: rutl.TestAntenner
FAIL something/mypackage [build failed]
Is there a way to do it?

Files matching *_test.go are only compiled when testing the package they are part of. If you are testing package A that uses package B, you won't have access to the _test.go code from package B.
So the two options are:
Always compile the test support code into package B.
If the test support code only depends on the exported interface of B, consider splitting it out into a separate package.

Related

How to annotate symbols that they are shared among other projects?

Suppose I have a Go project which act as shared library in another Go project. How do I markup Go symbols (consts, structs, vars) that they are used outside this project?
I guess the underlying problem is that I have a hard time knowing which code uses said symbols.
Please note: This is not about semantic versioning, of which I am very well aware and which I use. I know Semver can help to identify breaking changes.
Instead, this is about finding out if I actually break one of my own projects (compared to: This symbol should be unexported or used outside the package). I am thinking of some sort of annotation which don't exist in Go.
As an aside, IntelliJ doesn't know either and marks those symbols as "Unnecessarily exported". Maybe an IntelliJ-centric solution could suffice.
To illustrate my problem:
package sharedlib
import "time"
// MyFavoriteTimeFormat is a blablabla...
const MyFavoriteTimeFormat = Time.RFC3339
package dependingproject
import "github.com/thething/sharedlib"
import "time"
func convertToString(timestamp time.Time) string {
return timestamp.Format(sharedlib.MyFavoriteTimeFormat)
}
When I happily rename MyFavoriteTimeFormate and release it, the code will break in the depending project when it updates the dependency.
Don't export anything until some other package needs it. If another package needs something, then do export, and then you'll know that if something is exported, it is because it is used outside of the package. And do not do breaking changes on exported identifiers. If you really must, then increment major version. Using go modules, that won't break existing other packages, they will continue to use the old version.
If your module is broken down into multiple packages (because it is "big"), and you wish to export something solely for the other packages of your module, then use the internal package concept, so it will still be "unexported" (unimportable) to other modules. For details, see Can I develop a go package in multiple source directories?

Should functions/constants/variables be exported or not in `package main`?

I'm developing a tiny project that has a single package main. AFAIK, best-practice for small Golang binary projects is to have all code in a single (main) namespace, so that's what I've done.
Just curious, within a package main, is it best practice to keep functions/constants/variables exported (MyFunction) or unexported (myFunction)?
Really it doesn't matter. main packages can't be imported so whether you export them or not doesn't matter in that regard.
However if you do export them then tools like golint will encourage you to document them so maybe that's a good reason to go ahead an export them.
The most important thing is to be consistent. I prefer to name un-exported items in package main starting with lowercase even though they can't be exported. This is because it's an additional hint that these entities aren't used outside their containing package. You don't need to know that the declaration is in main to know that the thing being declared is not used externally.

Golang, Using a Structure or function of a main package from a sub package

I am trying to write a go project with several sub projects. For an simple example the project looks like this
Main
|- package one
|- package one.one
|- package one.two
|- package two
From my main package i can use any function or structure of any sub package By importing them. But My question is how can i access an struct or function of main from any sub package.
By importing the "subpackages" in main. But do not produce an import cycle (Restructure your code in this case).
Note that Go has (almost*) no notion of _sub_package: These are all plain packages and the directory layout has no influence on imports and usability/accessability of exported functions, types, methods, fields, variables and constants.
*) Internal packages and vendored packages depend on directory layout.
Thanks. I solved this problem by using an third package. Pretty easy that way.

Using binary packages directly

I'm writing a library in Go. I'm planning to distribute it, and with a main requirement of 'without source codes'.
For testing, I have created two workspaces like following,
WS1
bin/
pkg/linux_amd64/lib.a
src/lib/src.go
WS2
bin/
pkg/
src/main/main.go
My first workspace (WS1) is the actual dummy library, which has some utility functions. Second workspace (WS2) has main function which uses the package (lib.a) from WS1.
Everything was working good until I remove the sources from WS1. If I remove the directory /lib/src.go in WS1, I'm getting the following error during go build,
main.go:5:2: cannot find package "lib" in any of:
/usr/local/go/src/pkg/lib (from $GOROOT) ../Testing/ws1/src/lib
(from $GOPATH)
The above message indicates us that we should keep the source files as well. Precompiled binary packages alone cannot be used directly.
Based on few suggestions online, we may keep some dummy sources with timestamp value lesser than binary packages' timestamp. But, this doesn't seems to be a feasible solution for us. What happens if timestamp of the dummy sources got updated unfortunately?
I have seen similar issue discussed here,
https://github.com/golang/go/issues/2775
My Questions:
Distributing the sources is the only possibility in Golang?
Why Go is not providing a provision for using '.a' files directly?
If keeping the source is mandatory for Go, why this small thing is
not mentioned anywhere in Go? (or) Am I missing something here?
Thanks in advance for your help guys!
The Go compiler just needs the .a files. If you ship them anybody will be able to use your package without the source code.
BUT your users will have to invoke the compiler (e.g. 6g, not the go tool) manually. If you ship a myfoo.a file and a dummy source myfoo.go containing just package myfoo and the timestamp of myfoo.a is newer than that of myfoo.go (and you put everything in place) you may use the go tool.
Update: Newer version of the go tool detect deleted files and require all files (possibly empty) with the proper filenames and older timestamps in the src folder.
Managing a timestamp should not be a dealbreaker.
Don't get fooled that the go tool is Go: It is a dead convenient tool to build, test, get, whatever your Go code, but it is neither the language nor the compiler nor the linker.
BTW: There is really no point in not distributing the sources.
The binary-only packages will be available in go1.7 (August 2016) - https://tip.golang.org/doc/go1.7
This release adds experimental, minimal support for building programs using binary-only packages, packages distributed in binary form without the corresponding source code. This feature is needed in some commercial settings but is not intended to be fully integrated into the rest of the toolchain. For example, tools that assume access to complete source code will not work with such packages, and there are no plans to support such packages in the “go get” command.
The proposal is at https://github.com/golang/proposal/blob/master/design/2775-binary-only-packages.md , https://tip.golang.org/pkg/go/build/#hdr-Binary_Only_Packages has more information about the new feature.
The binary-only packages is supported in go 1.7 now.
You can only provide .a files and fake go files without source code to distribute it now.
Here is a detailed example and a script of Go1.7 binary package generator.
myframework/frameImplement.go
package myframework
import "fmt"
func Hello(name string) string {
return fmt.Sprintf("Hello, %s!", name)
}
main/main.go
package main
import (
"fmt"
"golang-binary-package-generator/myframework"
)
func main() {
fmt.Println(" start program ")
fmt.Println(" print program :", myframework.Hello("print something now"))
}
If I want to hide my framework's source code, just build it with go build -i -o $GOPATH/pkg/framework.a, then modify your source code to
//go:binary-only-package
package framework
//you can add function prototype here for go doc etc, but no necessary.
, which you can use my binary package generator(script) to help you.
The decision to drop the feature:
cmd/go: drop support for binary-only packages

Why can't I add a main to my library in golang?

I'm having trouble achieving what should be an easy task. I understand the GitHub model for code organization (ie a library repo and an app repo that consumes the library). I think it's fantastic. But I find often that I want mylib to come bundled with a simple executable in a single main.go file. The main.go should be package main and should import mylib. In other words, it should be an exact documentation of how to build an app that consumes this library.
My point is, since it is often enough convenient to provide a simple command line interface that wraps your library, there should be an easy way to do this without having to make another repo, and golang should help.
I'd like something like the following:
$GOPATH/src/github.com/me/mylib
mylib.go
mylib_also.go
main.go
where mylib is the library (package mylib) and main.go is package main and on running go install it generates bin/mylib and pkg/mylib.a.
Either main.go should import "github.com/me/mylib" (if I do that now, I get cyclical import error) or go would understand what's happening since this feature should be built in and the one main.go in the repo generates the exec. Probably requiring the import (and dropping the cyclical error) is the better way.
Right now, I have to do
$GOPATH/src/github.com/me/mylib
mylib/
mylib.go
main.go
So I have to import github.com/me/mylib/mylib which is ridiculous.
In sum, go install should allow the special case of a package and a main which imports the package and provides a simple cli that demonstrates the packages API. The GitHub model promotes two repos, but it should be easy to do simple clis in one!
You can't have multiple packages per folder. Go operates on a package-level, not a file level.
Convention in this case—a binary that consumes your library—is to create a cmd folder with your package main - i.e. as per https://github.com/bradfitz/camlistore/tree/master/cmd or https://github.com/boltdb/bolt
In your case this would be:
$GOPATH/src/github.com/me/mylib
mylib/
mylib.go
README.md
cmd/
your-lib-tool/
main.go
If you just want a convenient, little wrapper, just some command line interface to your lib for demonstration purpose and it is okay if the main program is not built on go get (and not during simple go build and go install) but you are okay by running it via go run main.go or building it manually e.g. with 6g: Just use a build tag (see http://golang.org/pkg/go/build/#hdr-Build_Constraints) in main.go:
// +build ignore
and you won't need a different folder or repo.

Resources