在GO中毒化套件/功能
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.
TLDR:golang中是否有办法“毒化”(即使有点不规范) p>
更长的版本:我正在编写一个节俭服务,所有面向公众的函数都将返回结果或某种类型的错误,声明为 旧文件。 代码生成器将为接口生成如下代码: p>
publicFacingFunc(...)(returnType,错误)
code> pre>
这很好,直到与我一起工作的人决定检查另一个条件,并且在不满足该条件时会执行以下操作: p>
if conditionIsNotMet {
返回nil,错误。New(...)
}
code> pre>
代码可以编译,但是当出现错误时,收到的消息是未记录的随机字符串 。 因此,在这些文件中,我想防止使用“错误”和“ fmt”软件包。 p>
是的,我尝试过,但在文件顶部仍然显示警告 ,但似乎没有人读。 p>
顺便说一句,所有公共错误都有各自的“构造函数”,这些结构位于这些文件的外部,在我的情况下,仅应使用那些。 / p>
div>
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.