2015-01-27 20 views
5

işaretli semantik temsil etmek için herhangi bir deyim varsa merak ediyorum. kapsamlı olarak kastettiğim şu:Golang'da deyimsel anlamlandırılmış semantik var mı?

  • (oneliner yerine açık Lock + deffered Unlock),
  • günlüğü işlevinin (veya herhangi bir kod bloğu) giriş ve çıkış,
  • ölçme yürütme zamanı muteks'i kapsamlı. İlk iki mermi

örnek kod:

package main 

import "log" 
import "sync" 

func Scoped(m *sync.Mutex) func() { 
    m.Lock() 
    return func() { 
     m.Unlock() 
    } 
} 

func Log(what string) func() { 
    log.Println(what, "started") 
    return func() { 
     log.Println(what, "done") 
    } 
} 

func main() { 
    defer Log("testing")() 

    m := &sync.Mutex{} // obviously mutex should be from other source in real life 
    defer Scoped(m)() 
    // use m 
} 

https://play.golang.org/p/33j-GrBWSq

Temelde biz bir işlev çağrısı sadece şimdi (örn muteks kilidi) yapmak gerekir, ve bir çağrı ertelendi edilmelidir ertelemek (örneğin mutex unlock). Burada sadece adlandırılmamış işlevi döndürmeyi öneriyorum, ancak kolayca adlandırılabilir (işlev alanına sahip struct).

Tek bir sorun var: kullanıcı ilk aramanın sonucunu 'aramayı' unutabilir.

Bu kod (olabilir) deyimsel mi?

+0

."Deyimsel" yolu açıkça 'lock()' ve sonra 'defer unlock()' –

+0

'u çağırmaktır. Bu yaklaşım [Effective Go trace örneğinde kullanılır. (Https://golang.org/doc/effective_go.html# erteleme). –

cevap

4

Bunu yapmak için deyimsel bir yol olduğuna inanmıyorum. Ben de neden istediğini bilmiyorum,

gerçekten çok kötü?

+2

Bu gerçekten idiyomik bir yoldur (Tanrı tüm bu saçmalık saçmalıklardan nefret etmeye başlıyorum), ancak OP tarafından önerilen model oldukça güzel IMO'dur. –

+0

'Logging motoru', sadece bir satır yazmanız gerektiğinde en iyisidir - daha fazla kullanıcının bazı küçük işlevlerde günlüğe kaydetme olasılığının artacağı olasılığı vardır. – Kokos

+0

Ayrıca, bozuk değişken (_j_ yerine _j_) kullanma veya örnek kaydedicimizde (dizge analiz araçlarında karışıklığa neden olabilecek) farklı dizeler yazabilme olasılığı vardır. – Kokos

3

Önerilen çözümünüz zaten güzel. Ayrıca defer'un sonunda aramanız gereken func türünde bir değer döndürürsünüz.

Sen (a func değer döndüren) önlemek, fakat 2 işlev çağrıları, başlangıç ​​ olayı ve olayı kaydeder başka bir oturum biri olmak zorunda olabilir.

Alternatif, defer ifadesiyle değerlendirilen ertelenmiş (bir işlev döndürmek yerine) işlevinin parametre değerini üreten bir işlev çağrısı yapmaktır ve bu şekilde hala bir satır kalabilir.

Ayrıca Go Playground üzerinde deneyebilirsiniz:

func start(s string) string { 
    fmt.Println("Started", s) 
    return s 
} 

func end(name string) { 
    fmt.Println("Ended", name) 
} 

func main() { 
    defer end(start("main")) 

    fmt.Println("Doing main's work...") 
} 

Çıktı:

Started main 
Doing main's work... 
Ended main 
0

Ben, soru idiomaticity git alakalı olmadığını düşünüyorum o zaman fonksiyon kodu hakkında ikna etmeye genellikle daha iyidir görünüyor aynı şekilde davranmak ya çağrı. Durumu korumak için, bir nesneyi daha iyi bir hale getirip, bu nesnede bir yöntem olarak işlev tanımlayacağım.

type message string 
func (foo message) Log(bar string){ 
    if bar==nil{doSomethingSpecial()} 
    switch foo{ 
     case something: doSomething() 
     ... 
     case nil: doSomethingInitial() 
     default: doDefault() 
    } 
    log.Println(bar, "started") 
    foo=bar 
} 
1

gibi bir şey bir kapsamı olarak anonim işlev atın Anlamı: Bunu yapmak için daha kısa bir yol düşünemiyorum

func() { 
    Entrance() 
    defer Exit() 
    // anything you want to do in this scope 
}()