2016-09-01 32 views
1

Goにプログラムを書く際に奇妙なバグが発生しました。Golang switch文が関数を1回だけ呼び出す

本質的に、私はswitch文をそれぞれのcaseがsetill関数を2回呼び出すことになっています。しかし、関連するケースが実行されるときには、関数を1回呼び出すだけです。ここで

は、コードスニペットです:

check := true 
    n, e, s, w := b.North, b.East, b.South, b.West 
    switch { 
    // NE (>) 
    case n.Closed && e.Closed: 
     check = check && p.setIll(s) 
     check = check && p.setIll(w) 
    // NS (\\) 
    case n.Closed && s.Closed: 
     check = check && p.setIll(e) 
     check = check && p.setIll(w) 
    // NW (^) 
    case n.Closed && w.Closed: 
     check = check && p.setIll(e) 
     check = check && p.setIll(s) 
    // ES (v) 
    case e.Closed && s.Closed: 
     check = check && p.setIll(n) 
     check = check && p.setIll(w) 
    // EW (//) 
    case e.Closed && w.Closed: 
     fmt.Println("Running setIll the first time") 
     check = check && p.setIll(n) 
     fmt.Println("Running it again") 
     check = check && p.setIll(s) 
     fmt.Println("And now we're done running") 
    // SW (<) 
    case s.Closed && w.Closed: 
     check = check && p.setIll(n) 
     check = check && p.setIll(e) 
    } 

はここsetIllです:

func (p Player) setIll(n *Node) bool { 
    fmt.Println("I'm running!") 
    p.Illegal.Nodes[n.Loc.X][n.Loc.Y].Closed = true 
    return !p.Forced.Nodes[n.Loc.X][n.Loc.Y].Closed 
} 

これは次の出力生成: "!私は実行している" ことを

Running setIll the first time 
I'm running! 
Running it again 
And now we're done running 

はお知らせ出力に1回だけ表示されます。なぜこれがあるかもしれないのか?

+2

' &&は "短絡"演算子で、左側のものが 'false'と評価された場合、右側を実行するのを邪魔することはありません(' false && whatever'は 'false'です)。もう少し詳しくお答えします。 – twotwotwo

答えて

3

switchあなたを引き上げるのではなく、それはどのように&&が動作するかです。

&&||short-circuiting演算子です:左側の結果は、答えがどうなるかを決定するのに十分であるならば、それらはすべてで右側に何があるかは実行されません。あなたの式がa && f()aの場合はfalseでしたので、最終結果がfalseになるようにf()を実行する必要はありません。 Goの仕様では、これは次のとおりです。"The right operand is evaluated conditionally."

これは多くの言語で共通です。あなたの最初のチェックが他のチェックを実行するのに合格する必要があるときに役立ちます。たとえば、Webアプリケーションでユーザーのアクセス許可を確認する場合は、ユーザーがすべてログインしている場合(user != nil):user != nil && user.HasPermission(requiredPerm)が必要です。あなたはいつもと呼ばれる二回しかしsetIllと、check VARあなたは今それをやっているのと同じ方法を設定したい場合は

、あなたはどの&&式の外で変数にsetIll結果を割り当てることができます。

ck1, ck2 := p.setIll(n), p.setIll(s) 
check = check && ck1 && ck2 
+0

また、 'check = p.setIll(...)&& check'。それが多かれ少なかれ読めるかどうかは分かりませんが、 – Vatine

関連する問題