2016-07-24 20 views
6

Global değişkenlerden kaçınmanız gerektiğini defalarca duydum. Benim örnekteGenel değişkenleri ne zaman kullanmalısınız

Bir işlev çağrısı veya ona benzer bir tekrar tekrar bu değişken bildirerek önlemek için sadece global myTypes değişken ilan etti.

Bu nasıl yapılmalı? Daha iyi bir yolu var mı? Daha test edilebilir bir yol?

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

cevap

6

Tek zamanki gibi

Method Value olan alıcı tipi *T taşımaktadır iki kimin alıcı tipi T taşımaktadır yöntemleri Mv, ve Mp, bir struct type T düşünün kullanmaktır.

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 

sentezleme

T.Mv 

Mv ama ilk değişken olarak bir açık alıcı ile işlevsel bağlantı verir;

: o genel değişkenin kurtulmak için Sen Yöntem bir örnek görebilirsiniz

func(tv T, a int) int 

İmza Değeri 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) 
} 

bir yolu yöntemi değerlerini kullanmaktır vardır

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

Küresel değerleriniz için yeni bir resmi yaklaşım olan Go 1.7'de context.Context#Values tanıtıldı.

Bağlam Değerlerini yalnızca isteğe bağlı parametreleri işlevlere geçirmek için değil, süreçleri ve API'leri ileten istek kapsamındaki veriler için kullanın.

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


Son olarak, teste sert olma yanında, küresel değerler vendoring önleyebilir.

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

Birçok Go kütüphanelerine ihraç var paket değişkenleri. Bu değişkenler, belirli bir paketin belirli küresel durumları olarak görülebilir.

Önceki satıcı çağında, içe aktarılan her paketi bir kez alabilir ve içe aktarılan her paketin genel durumu, diğer tüm içe aktarılan paketler içinde paylaşılabilir.

Bazı devreler, bunu kabul edildiği gibi alabilir ve yalnızca bu küresel durumları istedikleri gibi kullanabilir.
Ancak, her bir içe aktarılan paketin satıcılığına sahip , kendi global durumu olan kendi görünümüne sahip olabilir. Artık bir dev, diğer paketin global durum hakkındaki görünümünü değiştirmeyi imkansız görebiliyordu

3

Tüm global değişkenler kötüyse. Sizin durumunuzda:

  • Genel değişken main paketindedir ve bu nedenle yalnızca tek bir program tarafından erişilebilir. Tamamdır.
  • Genel değişken bir kere başlatılmış ve daha sonra değiştirilmemiştir. Tamamdır.

Diğer taraftan, programın çalıştırılması sırasında bir global değişken her değiştirildiğinde, programın anlaşılması zorlaşır. Bu nedenle kaçınılmalıdır. o paketin iki kullanıcının birbirlerini etkileyebilir çünkü yeniden kullanılabilir olması gerekiyordu bir pakette

, küresel değişkenler kaçınılmalıdır. json paketinin var Indent bool genel değişkenine sahip olduğunu düşünün. Böyle bir değişkenin, birileri JSON'u biçimlendirmek istediğinde yeniden yaratılan JsonFormatter gibi bir veri yapısının içinde gizlenmesi daha iyidir.

İlgili konular