はじめに
本記事は全30ステップで学ぶGolangをテーマにしたGolang学習フローのステップ8です。
この記事へ直接訪問された方は、ぜひ下記の記事を参考に自身の理解度をふまえて学習を開始してみてください。
前回までのあらすじ
前回のステップでは、Go言語の基本的な条件分岐(if文)について学びました。単純な条件での分岐制御と、Go言語特有の初期化付きif文について理解を深めました。今回は、これらの知識をベースに、より複雑な条件を作成するための論理演算子について学んでいきます。
【ステップ7】Go言語での条件分岐、if文の基礎論理演算子の基礎
Go言語には、条件を組み合わせるための3つの基本的な論理演算子があります。
ステップ8では一般的に論理的思考能力と言われる力をほんの少し求められます。A = BだからC
といった考え方です。噛み砕くとテストの点数によってA〜D判定があるようなイメージです。
「点数(A)が100点(=B)だから(だから)A判定(C)」といった物の考え方です。論理的思考能力と言われると難しく考えがちですが、日常的によく使う物事の考え方ですのでそこまで気にしなくても大丈夫です。
ただし、プログラムの基本はこの論理的思考による正誤判定の繰り返しです。「苦手だな?」と思った人は論理的思考能力を鍛えるトレーニングも一緒にしてみましょう!
またGithubからリポジトリをクローンした方は各項目に記載の sampleX
や exercisesX
がコードとリンクしています。
1. 論理積 AND演算子(&&)
両方の条件が真の場合にのみ、全体が真になります。
シンプルに2つの条件を満たす場合の例
package main
import "fmt"
func main() {
age := 25
income := 300000
if age >= 18 && income >= 250000 {
fmt.Println("クレジットカードの申し込み資格があります")
} else {
fmt.Println("申し込み条件を満たしていません")
}
}
2. 論理和 OR演算子(||)
少なくとも1つの条件が真の場合、全体が真になります。
条件のうち、いずれか一つの条件を満たす場合に真となります。
package main
import "fmt"
func main() {
isStudent := true
isElderly := false
if isStudent || isElderly {
fmt.Println("割引が適用されます")
} else {
fmt.Println("通常料金です")
}
}
3. 否定 NOT演算子(!)
条件の真偽を反転させます。
真偽を逆転させます。
package main
import "fmt"
func main() {
isClosed := false
if !isClosed {
fmt.Println("お店は営業中です")
} else {
fmt.Println("お店は閉店しています")
}
}
複雑な条件の組み立て
1. 比較演算子との組み合わせ
論理演算子は比較演算子と組み合わせて使用することができます。
実際に使われるパターンとして一番多いと思います。
やっていることは簡単なのでさくっと動きを確認してみましょう!
package main
import "fmt"
func main() {
score := 85
if score >= 80 {
fmt.Println("優秀な成績です")
} else if score >= 60 {
fmt.Println("合格です")
} else {
fmt.Println("不合格です")
}
}
2. 複数条件の組み合わせ
論理演算子を組み合わせることで、より複雑な条件を作成できます。
条件を組み合わせる事でより複雑な判定が行えます
package main
import "fmt"
func main() {
age := 20
isStudent := true
hasMembership := false
if (age < 18 || isStudent) && !hasMembership {
fmt.Println("学生割引が適用されます")
} else if hasMembership {
fmt.Println("会員割引が適用されます")
} else {
fmt.Println("通常料金です")
}
}
()
で条件をまとめる事で、計算式の括弧のように計算順序を指定できます。a == 1 || a == 2 && b == 1
だとaが1または2の時点でOR条件を満たしてしまい、bの判定が不要となります。(a == 1 || a == 2) && b == 1
とすることで、aが1または2で、かつbが1の時
と正しく条件がかけます。
3. 短絡評価(Short-circuit evaluation)
Go言語の論理演算子は短絡評価を行います。これは、左から右へ評価を行い、結果が確定した時点で評価を停止する機能です。
プログラム言語には結構実装されている事が多い仕組みです。
これを覚えておくと処理速度が早いプログラムを書くことができます。またエラーとならない処理を書くためにも必要なケースもあるので覚えておきましょう。
package main
import "fmt"
func main() {
age := 15
income := 250000
// 比較が行われないというのをわかりやすくするために、checkIncomeという変数型関数を定義。
checkIncome := func(i int) bool{
fmt.Println("incomeをチェックしています")
return i >= 200000
}
// ageが18未満なので、checkIncomeは実行されない
if age >= 18 && checkIncome(income) {
fmt.Println("条件を満たしています")
} else {
fmt.Println("条件を満たしていません")
}
}
比較しないといけない!でも値が無い時もありえるから比較するとnull pointer exceptionしちゃう・・・!なんて時に存在確認 && 値検証
という書き方をすると、存在確認でfalseになれば値検証がされず、エラーがでなくなります。
今はまだふんわりと「そういうこともあるんだ」とおぼえておきましょう!いつかこれのことだったのか!とわかる時がきます。
実践的な演習問題
ユーザーから年齢、学生かどうか、平日かどうか、メンバーズカードの有無を入力として受け取り、適用される割引と最終的な料金を表示してください。
曜日はtime.Time型からWeekday()メソッドで取得できます。
・基本料金1800円
・13歳未満:基本料金の50%
・65歳以上:基本料金の70%
・学生(25歳以下):基本料金の80%
・平日:100円引き
・メンバーズカード所持:さらに5%オフ
クリックして答えを見る
package main
import (
"fmt"
"log"
)
func main() {
var age int
var isAcademy, hasCard bool
var discountRate float64
var err error
discountRate = 1.0
base := 1800.0
price := 0.0
fmt.Println("年齢を入力してください")
_, err = fmt.Scan(&age)
if err != nil {
log.Fatalln("年齢の入力にエラーがあります:", err)
}
fmt.Println("学生ですか?")
_, err = fmt.Scan(&isAcademy)
if err != nil {
log.Fatalln("学生判定の入力にエラーがあります:", err)
}
fmt.Println("メンバーカードを持っていますか?")
_, err = fmt.Scan(&hasCard)
if err != nil {
log.Fatalln("メンバーカード判定の入力にエラーがあります:", err)
}
w := time.Now().Weekday()
if age < 13 {
discountRate = 0.5
} else if age >= 65 {
discountRate = 0.7
} else if isAcademy && age <= 25 {
discountRate = 0.8
}
if hasCard {
discountRate -= 0.05
}
price = base * discountRate
if !(w == time.Saturday || w == time.Sunday) {
price -= 100
}
fmt.Println(fmt.Sprintf("本日の映画料金は、%f円です", price))
}
年齢がマイナスの場合は 0未満の場合
で判定することができます。
以下の条件をチェックします
・長さが8文字以上
・少なくとも1つの大文字を含む
・少なくとも1つの小文字を含む
・少なくとも1つの数字を含む
・少なくとも1つの特殊文字(!@#$%^&*)を含む
それぞれの条件を個別にチェックし、満たしていない条件を表示してください。
まだ学んでいない処理を実行する必要があります。これを調べながら作ることができたらエンジニア適正高いです!挑戦してみてください!
クリックして答えを見る
package main
import (
"fmt"
"log"
)
func main() {
var pw string
var err error
fmt.Println("パスワードを入力してください")
_, err = fmt.Scan(&pw)
if err != nil {
log.Fatalln("PWの入力にエラーがあります:", err)
}
if len(pw) < 8 {
fmt.Println("パスワードは8文字以上入力してください")
}
hasUpper := false
for _, r := range pw {
if unicode.IsUpper(r) {
hasUpper = true
break
}
}
if !hasUpper {
fmt.Println("パスワードは少なくとも1つの大文字を含めてください")
}
hasLower := false
for _, r := range pw {
if unicode.IsLower(r) {
hasLower = true
break
}
}
if !hasLower {
fmt.Println("パスワードは少なくとも1つの小文字を含めてください")
}
hasNumber := false
for _, r := range pw {
if '0' <= r && r <= '9' {
hasNumber = true
break
}
}
if !hasNumber {
fmt.Println("パスワードは少なくとも1つの数字を含めてください")
}
hasSpecial := false
specialChar := "!@#$%^&*"
for _, r := range pw {
for _, s := range specialChar {
if r == s {
hasSpecial = true
break
}
}
}
if !hasSpecial {
fmt.Println("パスワードは少なくとも1つの特殊文字を含めてください")
}
}
年齢がマイナスの場合は 0未満の場合
で判定することができます。
サンプルと演習問題の動くコードを公開!
Githubにて各ステップのコードを公開しています。cloneして動かしてみたり、手を入れて理解を深めてください。
ぜひStarでの評価をお願いします!
次のステップへのつながり
論理演算子と複雑な条件の扱い方を理解したことで、より精密な条件分岐を実装できるようになりました。次のステップでは、ループの基礎(for文)について学びます。これにより、繰り返し処理を実装できるようになり、より効率的なプログラムを作成できるようになります。