我多次听说你应该避免全局变量.
在我的例子中,我声明了一个全局myTypes变量,只是为了避免在函数调用或类似的东西中反复声明该变量.
这是怎么做的?有没有更好的办法?一种更可测试的方式?
var myTypes = map[string]string{
"type1": "tpl1",
"type2": "tpl2",
}
func AFunc(someType string) string {
fmt.Sprintf("this is your type %s", myTypes[someType])
}
func main() {
AFunc("type1")
}
Run Code Online (Sandbox Code Playgroud)
并非所有全局变量都是坏的.在你的情况下:
main包中,因此只能由单个程序访问.还行吧.另一方面,每当在程序执行期间修改全局变量时,程序就变得更难理解.因此应该避免.
在一个可重用的包中,应该避免全局变量,因为那个包的两个用户可能会相互影响.想象一下,如果json包具有全局变量var Indent bool.这样的变量最好隐藏在数据结构中,就像JsonFormatter每次有人想要格式化一些JSON时重新创建一样.
一种常用方法是使用方法值
考虑
struct type T使用两种方法,Mv其接收器是类型的T,并且Mp其接收器是类型的*T.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
Run Code Online (Sandbox Code Playgroud)
表达方式
T.Mv
Run Code Online (Sandbox Code Playgroud)
产生一个等效于Mv的函数,但是有一个显式接收器作为它的第一个参数; 它有签名
func(tv T, a int) int
Run Code Online (Sandbox Code Playgroud)
您可以在此线程中看到方法值的示例
// TODO: Get rid of the global variable.
var foo service
func handleFoo(w http.ResponseWriter, req *http.Request) {
// code that uses foo
}
func main() {
foo = initFoo()
http.HandleFunc("/foo", handleFoo)
}
Run Code Online (Sandbox Code Playgroud)
摆脱全局变量的一种方法是使用方法值:
type fooHandler struct {
foo service
}
func (h fooHandler) handle(w http.ResponseWriter, req *http.Request) {
// code that uses h.foo
}
func main() {
foo := initFoo()
http.HandleFunc("/foo", fooHandler{foo}.handle)
}
Run Code Online (Sandbox Code Playgroud)
Go 1.7中引入了一种新的官方方法来实现您的全局价值context.Context#Values.
仅将上下文值用于转换进程和API的请求范围数据,而不是将可选参数传递给函数.
请参阅" 如何在Go 1.7中正确使用context.Context "
最后,除了难以测试之外,全球价值观还可以防止出售.
请参阅" 供应商或不供应商,这是一个问题 "
许多Go的库都导出了包变量.这些变量可以被视为某个包的某些全局状态.
在以前的销售时代,我们可以获得每个导入的包一次,并且可以在所有其他导入的包中共享每个导入包的全局状态.
一些开发者可能会认为它是理所当然的,只是随意操纵这些全球状态.
但是,通过销售每个导入的包可能有自己的全局状态视图.现在,开发者可能会发现无法改变其他包的全局状态观
| 归档时间: |
|
| 查看次数: |
4960 次 |
| 最近记录: |