Go言語(Golang)は、シンプルで効率的な記述ができるプログラミング言語として、多くのエンジニアに利用されています。
システム開発において、条件分岐はプログラムの挙動を制御する非常に重要な要素です。
その条件分岐を支えるのが、今回解説する「論理演算子」です。
論理演算子を正しく理解することで、複雑な条件を簡潔に表現し、バグの少ないコードを記述できるようになります。
本記事では、Go言語における論理演算子(AND, OR, NOT)の基本的な使い方から、実務で役立つ判定ルール、さらには「短絡評価」という重要な仕組みについて詳しく整理していきます。
Go言語における論理演算子の基本
Go言語で利用される主な論理演算子は、「&&(論理積)」「||(論理和)」「!(論理否定)」の3種類です。
これらの演算子は、主に bool 型(真偽値)のデータに対して操作を行います。
Go言語は静的型付け言語であり、型に対して非常に厳格な性質を持っています。
そのため、他のプログラミング言語(C言語やPythonなど)のように、数値の「0」や空文字列を暗黙的に偽(false)として扱うことはできません。
必ず true または false の結果を返す比較式や変数を用いる必要があります。
AND演算子 (&&) の使い方
AND演算子 && は、2つの条件が「どちらも真(true)である場合」にのみ、全体として true を返します。
一方でも false であれば、結果は false になります。
日本語では「かつ」と訳されることが多い演算子です。
package main
import "fmt"
func main() {
// 両方の条件が満たされている場合
hasLicense := true
hasCar := true
if hasLicense && hasCar {
fmt.Println("ドライブに行くことができます。")
} else {
fmt.Println("ドライブには行けません。")
}
}
ドライブに行くことができます。
OR演算子 (||) の使い方
OR演算子 || は、2つの条件のうち「少なくとも一方が真(true)である場合」に、全体として true を返します。
両方が false の場合のみ、結果が false となります。
日本語では「または」と表現されます。
package main
import "fmt"
func main() {
// どちらかの条件が満たされていれば良い場合
isWeekend := true
isHoliday := false
if isWeekend || isHoliday {
fmt.Println("今日は休みです。")
} else {
fmt.Println("今日は仕事です。")
}
}
今日は休みです。
NOT演算子 (!) の使い方
NOT演算子 ! は、真偽値を「反転させる」役割を持ちます。
true に付ければ false になり、false に付ければ true になります。
条件を否定したい場面で多用されます。
package main
import "fmt"
func main() {
isLoggedIn := false
// ログインしていない(NOT true)場合を判定
if !isLoggedIn {
fmt.Println("ログインが必要です。")
}
}
ログインが必要です。
論理演算子の真偽値表(真理値表)
各演算子の結果を一覧にまとめると、以下のようになります。
| 条件A | 条件B | A && B (AND) | A || B (OR) | !A (NOT) |
|---|---|---|---|---|
| true | true | true | true | false |
| true | false | false | true | false |
| false | true | false | true | true |
| false | false | false | false | true |
短絡評価(ショートサーキット)の仕組み
Go言語の論理演算子において非常に重要なのが、「短絡評価(ショートサーキット評価)」という挙動です。
これは、「式全体の結果が確定した時点で、残りの評価を打ち切る」という最適化の仕組みです。
この仕組みを理解していないと、意図しないバグを生んだり、逆にこれを活用してコードを安全に記述したりすることができます。
AND演算子の短絡評価
AND演算子 && では、左側の式が false だった場合、右側の式が何であっても全体の結果は必ず false になります。
そのため、Go言語は左側が false の時点で右側の評価を行いません。
package main
import "fmt"
func main() {
var str *string = nil
// strがnilでないことを先に確認する(短絡評価の活用)
// もしstrがnilなら、右側の *str == "Go" は実行されないためパニックを防げる
if str != nil && *str == "Go" {
fmt.Println("Matched!")
} else {
fmt.Println("Not matched or nil.")
}
}
上記の例では、もし短絡評価がなければ nil へのデリファレンスが発生し、プログラムがクラッシュしてしまいます。
OR演算子の短絡評価
OR演算子 || では、左側の式が true だった場合、右側の式が何であっても全体の結果は必ず true になります。
そのため、左側が true の時点で右側の評価をスキップします。
package main
import "fmt"
func checkStatus() bool {
fmt.Println("関数が実行されました")
return true
}
func main() {
isReady := true
// isReadyがtrueなので、右側のcheckStatus()は実行されない
if isReady || checkStatus() {
fmt.Println("準備完了です。")
}
}
準備完了です。
このように、関数の実行コストが高い場合や副作用がある場合には、短絡評価の性質を意識することが大切です。
論理演算子の優先順位
複数の論理演算子を一つの式で使う場合、計算される順番(優先順位)が決まっています。
Go言語における論理演算子の優先順位は高い順に以下の通りです。
!(NOT)&&(AND)||(OR)
例えば、A || B && C という式は、「A または (B かつ C)」という意味になります。
左から順番に評価されるわけではない点に注意が必要です。
優先順位を明確にするための括弧 ( )
演算子の優先順位に依存しすぎると、コードの可読性が低下し、勘違いによるバグの原因となります。
意図した順序で評価させたい場合や、読みやすくしたい場合は積極的に半角の括弧 () を使用しましょう。
package main
import "fmt"
func main() {
isMember := true
hasCoupon := false
isSpecialDay := true
// メンバーであり、かつ(クーポンを持っているか、または特別な日である)
if isMember && (hasCoupon || isSpecialDay) {
fmt.Println("割引が適用されます。")
}
}
このように括弧を使うことで、どの条件がグループ化されているかが一目でわかります。
Go言語における論理演算子の注意点
Go言語は他の言語に比べて型に厳しいため、特有の注意点があります。
1. bool型以外には使えない
C言語やJavaScriptのように、数値やポインタを直接 if 文の条件式に入れることはできません。
必ず bool 型の比較結果を渡す必要があります。
// NGなコード
// n := 10
// if n { ... } // コンパイルエラー
// OKなコード
n := 10
if n != 0 {
// 処理
}
論理演算子 && や || の左右も、必ず bool 型の結果を返す式である必要があります。
2. 比較演算子との優先順位
論理演算子は、比較演算子(==, !=, <, > など)よりも優先順位が低いです。
そのため、 x > 0 && y < 10 と書いた場合、正しく (x > 0) && (y < 10) と解釈されます。
これは直感に沿った挙動ですが、複雑な式になる場合はやはり括弧を用いるのが安全です。
ド・モルガンの法則を活用したリファクタリング
論理演算を扱う際、コードの可読性を高めるために「ド・モルガンの法則」を知っておくと便利です。
この法則は、否定演算を含む複雑な条件式をシンプルに書き換えるための論理学の法則です。
!(A && B)は!A || !Bと等しい!(A || B)は!A && !Bと等しい
例えば、「エラーがない、かつデータが空ではない」という条件を反転させて判定する場合などに役立ちます。
条件式があまりにも複雑になり、!(NOT)が多用されている場合は、この法則を使って式を整理できないか検討してみてください。
実践的な条件判定のパターン
Go言語の実務で見かける、論理演算子の典型的な活用パターンをいくつか紹介します。
ガード句としての利用
関数の冒頭で不適切な条件を排除する「ガード句」において、論理演算子は多用されます。
func processData(data *Data) error {
if data == nil || data.ID == "" {
return fmt.Errorf("invalid data")
}
// メインの処理
return nil
}
ここではOR演算子の短絡評価を利用し、data が nil であれば data.ID へのアクセスを行わずにエラーを返しています。
フラグ管理と条件の組み合わせ
アプリケーションの設定やステータスを複数のフラグで管理している場合、論理演算子を組み合わせて複雑な状態を表現します。
canEdit := isAdmin || (isOwner && !isLocked)
「管理者である」か、あるいは「オーナーであり、かつロックされていない」場合に編集を許可するというロジックです。
このように、ビジネスロジックを宣言的に記述できるのが論理演算子の強みです。
まとめ
Go言語の論理演算子(AND, OR, NOT)は、シンプルながらも非常に強力なツールです。
本記事で紹介した以下のポイントを意識することで、より高品質なコードを記述できるようになります。
- && (AND) は両方が真のときに真となる。
- || (OR) はどちらか一方が真のときに真となる。
- ! (NOT) は真偽値を反転させる。
- 短絡評価により、不要な評価はスキップされ、安全なコード記述に寄与する。
- 優先順位を意識し、複雑な条件では括弧
()を使って可読性を高める。 - Go言語は型に厳しいため、必ず bool 型で判定を行う必要がある。
論理演算はプログラミングの基礎中の基礎ですが、正しく使いこなすことでコードの意図が明確になり、メンテナンス性も大幅に向上します。
日々の開発の中で、よりシンプルで読みやすい条件式を書くための参考にしてください。
