概要
- 前回のつづき
- 今回は、変数のシャドーイング(隠蔽)や、制御構文、関数についての学習
- 今回もJavaやts(typeScript)と比較しつつ、進める。
インプット資料
シャドーイング
- ブロックの外と内で同じ変数を宣言した場合の動作
- 内では、外の変数はシャドーイング(隠蔽)される。そのため、外の変数はアクセスできなくなる
- 内を抜けたら、外の変数が参照される
- バグの温床になるので、シャドーイングはしない。
x := 10
{
fmt.Println(x) //10
x := 5
fmt.Println(x) //5 -> x:=10のシャドーイング発生
}
fmt.Println(x) // 10 → x:=10のシャドーイング解除
- (補足)Javaの場合
- ブロック外と内での変数宣言は、重複ローカル変数となり、コンパイルエラーになる。
- クラス変数とローカル変数で同じ変数を宣言した場合は、
this
で区別する。 - シャドーイングが発生するのは、継承関係にあるクラスのクラス変数が重複した場合。
- ※Goではクラスの継承自体がないので、そもそもで発生しない。
制御構文
- 共通して、条件を記載する箇所に
()
は不要。
if
- if文の条件の前に、変数を宣言できる。
- 宣言した変数は
if-else
内のブロックスコープとなる
rand.NewSource(time.Now().UnixNano())
// ブロック内のみ有効な変数「n」
if n := rand.Intn(10); n == 5 {
fmt.Println("nは5",n)
} else if n < 5 {
fmt.Println("nは5未満",n)
} else {
fmt.Println("nは5より上",n)
}
// ブロック外ではエラーとなる
//fmt.Println("nは",n)
for
- 繰り返しはfor文でのみ行う。whileはない。(代替する書き方はもちろんある。)
- 他の言語同様、breakやcontinueもある。gotoやラベル遷移もあるが、処理が追いづらくなるので、使用箇所には注意する。
- for文には以下の4種類ある。
- 通常のfor文
- 拡張for文
-
for-range
構文。配列やsliceなどを走査する場合に利用する。 - 引数を2つ(indexとvalue)とる。index不要の場合は、変数名を
_
にする(tsと同様) - for-rangeで宣言した値はコピーであるため、変更しても元の配列には影響しない( =イミュータブル)
-
- 条件のみfor文
- while文の代わり
- 条件なしfor文
- 無限ループ
// 通常のfor文
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// 拡張for文
evenVal := []int{1,2,3,4,5,6}
// index不要の場合「_」にする。なお、2つめ(value)が不要の場合は宣言しないでよい。
for _, v := range evenVal {
if v % 2 == 0 {
fmt.Println(v)
}
}
// 条件のみfor文(while文)
i := 2
for i < 10 {
fmt.Println(i)
i = i * 2
}
// 条件なしfor文(無限ループ)
n := 1;
for {
fmt.Println(n)
if n > 5 {
break
}
n++
}
switch
- switch内で有効となる変数宣言ができる
- csse文ではbreak記載しない。フォールスルーしたいときは、カンマで区切って、一つのcase式で複数の値を列挙する
- switch文に条件式を書かなくてもよい。(ブランクswitch)その場合、case文に条件式を書ける。
- 特定の変数に対する条件分岐の場合は、if文より、switch文を推奨
rand.NewSource(time.Now().UnixNano())
// ブロック内のみ有効な変数「n」
switch n := rand.Intn(12); n {
case 2,4,6,8,10:
fmt.Println("10までの偶数です。",n)
case 1,3,5,7,9:
fmt.Println("10までの奇数です。",n)
default:
fmt.Println("その他。",n)
}
// ブロック外ではエラーとなる
//fmt.Println("nは",n)
// ブランクswitch
// switch内で条件式を書かず、case内に書くこともできる
switch n := rand.Intn(12); {
case n % 2 == 0 && n <= 10:
fmt.Println("10までの偶数です。",n)
case n % 2 != 0 && n <= 10:
fmt.Println("10までの奇数です。",n)
default:
fmt.Println("その他。",n)
}
おわりに
- 制御ブロック内のみで有効な変数を宣言できるのは便利
- while文をfor文に統合したのは、シンプルでよいと思う。
- 元々while文はbreak条件の見通しが悪いから使用頻度も低いので。
- switch文が便利で使いやすくなったが、if文との使い分けが難しくなりそう。