エンジニアになりたい人募集!X(旧Twitter)からフォローしたらリプライで質問常時OK!

【ステップ8】Go言語の論理演算子とより複雑な条件

はじめに

本記事は全30ステップで学ぶGolangをテーマにしたGolang学習フローステップ8です。
この記事へ直接訪問された方は、ぜひ下記の記事を参考に自身の理解度をふまえて学習を開始してみてください。

【全30ステップ】Golangで始めるプログラミング学習

前回までのあらすじ

前回のステップでは、Go言語の基本的な条件分岐(if文)について学びました。単純な条件での分岐制御と、Go言語特有の初期化付きif文について理解を深めました。今回は、これらの知識をベースに、より複雑な条件を作成するための論理演算子について学んでいきます。

【ステップ7】Go言語での条件分岐、if文の基礎

論理演算子の基礎

Go言語には、条件を組み合わせるための3つの基本的な論理演算子があります。

ステップ8では一般的に論理的思考能力と言われる力をほんの少し求められます。
A = BだからC といった考え方です。噛み砕くとテストの点数によってA〜D判定があるようなイメージです。
「点数(A)が100点(=B)だから(だから)A判定(C)」といった物の考え方です。論理的思考能力と言われると難しく考えがちですが、日常的によく使う物事の考え方ですのでそこまで気にしなくても大丈夫です。
ただし、プログラムの基本はこの論理的思考による正誤判定の繰り返しです。「苦手だな?」と思った人は論理的思考能力を鍛えるトレーニングも一緒にしてみましょう!

またGithubからリポジトリをクローンした方は各項目に記載の sampleXexercisesX がコードとリンクしています。

1. 論理積 AND演算子(&&)

両方の条件が真の場合にのみ、全体が真になります。

論理積のサンプル: sample1

シンプルに2つの条件を満たす場合の例

go
package main

import "fmt"

func main() {
    age := 25
    income := 300000

    if age >= 18 && income >= 250000 {
        fmt.Println("クレジットカードの申し込み資格があります")
    } else {
        fmt.Println("申し込み条件を満たしていません")
    }
}

2. 論理和 OR演算子(||)

少なくとも1つの条件が真の場合、全体が真になります。

論理和のサンプル: sample2

条件のうち、いずれか一つの条件を満たす場合に真となります。

go
package main

import "fmt"

func main() {
    isStudent := true
    isElderly := false

    if isStudent || isElderly {
        fmt.Println("割引が適用されます")
    } else {
        fmt.Println("通常料金です")
    }
}

3. 否定 NOT演算子(!)

条件の真偽を反転させます。

否定のサンプル: sample3

真偽を逆転させます。

go
package main

import "fmt"

func main() {
    isClosed := false

    if !isClosed {
        fmt.Println("お店は営業中です")
    } else {
        fmt.Println("お店は閉店しています")
    }
}

複雑な条件の組み立て

1. 比較演算子との組み合わせ

論理演算子は比較演算子と組み合わせて使用することができます。

比較演算子との組み合わせのサンプル: sample4

実際に使われるパターンとして一番多いと思います。
やっていることは簡単なのでさくっと動きを確認してみましょう!

go
package main

import "fmt"

func main() {
    score := 85

    if score >= 80 {
        fmt.Println("優秀な成績です")
    } else if score >= 60 {
        fmt.Println("合格です")
    } else {
        fmt.Println("不合格です")
    }
}

2. 複数条件の組み合わせ

論理演算子を組み合わせることで、より複雑な条件を作成できます。

複数条件のサンプル: sample5

条件を組み合わせる事でより複雑な判定が行えます

go
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言語の論理演算子は短絡評価を行います。これは、左から右へ評価を行い、結果が確定した時点で評価を停止する機能です。

短絡評価のサンプル: sample6

プログラム言語には結構実装されている事が多い仕組みです。
これを覚えておくと処理速度が早いプログラムを書くことができます。またエラーとならない処理を書くためにも必要なケースもあるので覚えておきましょう。

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になれば値検証がされず、エラーがでなくなります。
今はまだふんわりと「そういうこともあるんだ」とおぼえておきましょう!いつかこれのことだったのか!とわかる時がきます。

実践的な演習問題

問1:映画館の料金計算プログラムを作成してください: exercises1

ユーザーから年齢、学生かどうか、平日かどうか、メンバーズカードの有無を入力として受け取り、適用される割引と最終的な料金を表示してください。
曜日はtime.Time型からWeekday()メソッドで取得できます。

・基本料金1800円
・13歳未満:基本料金の50%
・65歳以上:基本料金の70%
・学生(25歳以下):基本料金の80%
・平日:100円引き
・メンバーズカード所持:さらに5%オフ

クリックして答えを見る
go
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未満の場合 で判定することができます。

問2:パスワードの強度チェックプログラムを作成してください: exercises1

以下の条件をチェックします

・長さが8文字以上
・少なくとも1つの大文字を含む
・少なくとも1つの小文字を含む
・少なくとも1つの数字を含む
・少なくとも1つの特殊文字(!@#$%^&*)を含む
それぞれの条件を個別にチェックし、満たしていない条件を表示してください。
まだ学んでいない処理を実行する必要があります。これを調べながら作ることができたらエンジニア適正高いです!挑戦してみてください!

クリックして答えを見る
go
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文)について学びます。これにより、繰り返し処理を実装できるようになり、より効率的なプログラムを作成できるようになります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)