TLDR: Is there a way in golang (even if it is a bit non-standard), to "poison" a function or import of a certain package altogether.
The longer version: I am writing a thrift service, which all public facing functions return results, or an error of a certain type, declared in the thrift file. The code generator generates code for the interface like this:
publicFacingFunc(...) (returnType, error)
This would be great, until someone I am working with decides to check for another condition, and when that condition is not met does something like this:
if conditionIsNotMet {
return nil, errors.New(...)
}
The code compiles, but when the error arises, the received message is undocumented random string. So in these files, I want to prevent usage of "errors" and "fmt" packages.
And yes, I tried, and still have I a blaring warning at the top of the file, but nobody seems to read.
BTW, the public errors all have a respective "constructor", which is external to these files, and only those should be used, in my case.
If you're only concerned with a packages use within a file, you could import it under a silly name, like 'NEVER'... and people could use it, but they'd get the idea I think.
import (
NEVER "fmt"
)
OR, if you want to be less silly, you could use the _
underscore, https://golang.org/doc/effective_go.html#blank_import
import (
_ "fmt"
)
which will load the import, but only it's side effects (that is, not for explicit use.
To stop the input of all errors not of a certain type, you could use reflect
in order to stop the undesirable types with type assertion, https://golang.org/ref/spec#Type_assertions
v, ok = x.(T)
So if an err
comes up in the public facing function, that you don't want passed through, check what kind of error it is,
specialError, ok := err.(mypackage.ErrorType)
if !ok {
// don't send this error on
}
If you really want to enforce it, you could do a build step that checks the output of go list
for all of your packages, and make sure fmt
and errors
are not in the list of direct imports. With such common packages though, it could be difficult to avoid altogether. You could do more detailed parsing to detect fmt.Errorf
or whatever, but could be tricky.
A more invasive solution would be modifying package source for those packages and forcing devs to use your custom go distribution. Probably too hard to pull off for the fmt
and errors
packages that are used literally everywhere in the std lib, but it may work for other packages. I would never recommend it though. Definitely add it as a build-time validation that runs on checkins and PRs and things.