douzhulv1699 2016-07-24 12:36
浏览 29
已采纳

何时使用全局变量

I've heard many times that you should avoid global variables.

In my example I declared a global myTypes variable only to avoid declaring that variable over and over again in a function call or something similar.

Is this how it should be done? Is there a better way? A more testable way?

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")
}
  • 写回答

3条回答 默认 最新

  • dorbmd1177 2016-07-24 12:45
    关注

    One usual way is to use Method Value

    Consider a struct type T with two methods, Mv, whose receiver is of type T, and Mp, whose receiver is of type *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
    

    The expression

    T.Mv
    

    yields a function equivalent to Mv but with an explicit receiver as its first argument; it has signature

    func(tv T, a int) int
    

    You can see an example of Method Value in this thread

    // 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)
    }
    

    One way to get rid of that global variable is to use method values:

    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)
    }
    

    A new official approach for your global values is introduced in Go 1.7 with context.Context#Values.

    Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.

    See "How to correctly use context.Context in Go 1.7"


    Finally, in addition of being hard to test, global values can prevent vendoring.

    See "To vendor or not to vendor, that is a question"

    Many Go’s libaries have exported package variables. Those variables can be viewed as certain global states of a certain package.

    Prior vendoring era, we can go get each imported package once and the global state of each imported package can be shared within all other imported packages.

    Some devs may take it as granted and simply manipulate those global states at will.
    However, with vendoring each imported package may have its own view of global states. Now a dev may found it impossible to change other package’s view of global state

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 phython如何实现以下功能?查找同一用户名的消费金额合并—
  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿速度
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址