はじめに
Goをはじめて1年半。アウトプットが進まない私が、専門家の@tenntennさんから受けたマンツーマンレッスンの内容をまとめて、Goのスキルアップを目指します。Goの基礎から丁寧に学んでいきます。
記事のまとめは以下の通りで順次作成していきます。
今回は「2.基本構文」になります。
シリーズの一覧
- Goについて知っておく事
- 基本構文(今回)
- 関数と型
- パッケージとスコープ
本記事の内容
今回学ぶ内容は以下の通りです。
- 変数
- 定数
- 制御構文
- 条件分岐
- 繰り返し
組み込み型
定数、変数を取り扱うにあたって、ここで紹介しておきます。Goでは以下の型が組み込み型として用意されています。組み込み型の種類と同時に、Goでは重要になってくるゼロ値も記載しました。
ユーザ定義型については今回の記事では説明しません。
型名 | 説明 | ゼロ値 |
---|---|---|
int, int8, int16, int32, int64 | 符号付き整数型. intは32または64bit | 0 |
uint, uint8, uint16, uint32, uint64 | 符号なし整数型. uintは32または64bit | 0 |
float32, float64 | 浮動小数点数 | 0 |
uintptr | ポインタ値を格納するのに十分な大きさの符号なし整数型 | 0 |
byte | uint8のエイリアス | 0 |
rune | int32のエイリアス | 0 |
string | 文字列 | "" |
bool | 真偽値 | false |
error | エラー | nil |
参考:https://golang.org/ref/spec#Types |
#変数宣言
参考:https://golang.org/ref/spec#Variable_declarations
###型指定による変数宣言
Goは静的型付け言語なので、変数には型が存在します。変数宣言の基本構文はvar 識別子 型
ですが、その他にも色々な書き方ができます。
C言語のように変数を初期化する必要はなく、宣言時にゼロ値に初期化されます。(各組み込み型のゼロ値は、組み込み型の一覧を参照)
var n int // 変数nをint型で宣言する(ゼロ値で初期化される)
var a, b, c int // 変数a,b,cをint型で宣言する(ゼロ値で初期化される)
var n int = 100 // 変数nをint型で宣言し、100を代入する
var a, b, c int = 1,2,3 // 変数a,b,cをint型で宣言し、a=1,b=2,c=3を代入する
###型推論による変数宣言
変数を宣言する際に型を省略して書くこともできます。この場合、型無しの変数が作られるのではなく、型推論によってデフォルトの型で変数が作られます。
// 右辺100が整数のため、型推論により変数nをint型で宣言し、100を代入する
var n = 100
// 変数aをint型で宣言し、1を代入する
// 変数bをfloat64で宣言し、3.4を代入する
var a, b = 1, 3.4
さらにvarを省略して書くこともできます。ただし、この書き方は関数内でしか使えません。
// varは省略可能。ただし関数内しか使えない。
// 右辺100が整数のため、型推論により変数nをint型で宣言し、100を代入する
n := 100
// 変数aをint型で宣言し、1を代入する
// 変数bをfloat64で宣言し、3.4を代入する
a, b := 1, 3.4
まとめて書くこともできます。この書き方をグループ化と言います。
// まとめて書くこともできる
var (
n = 100
a, b, c = 1, 2, 3
)
型推論によるデフォルトの型
種類 | デフォルトの型 |
---|---|
整数 | int |
浮動小数点数 | float64 |
ルーン | rune |
文字列 | string |
真偽値 | bool |
ちなみに、Goは未使用の変数を許さないため、未使用変数があるとビルドエラーになります。
The Go Playground
./main.go:4:6: n declared and not used Go build failed.
#定数宣言
定数はコンパイル時から値が変わらないものです。名前無しの定数と名前付きの定数、定数式があります。
###名前無し定数
名前無し定数には以下のような種類があります。数値リテラルには2進数,8進数,16進数も用意されています。
参考:https://golang.org/ref/spec#Integer_literals
種類 | 例 |
---|---|
数値リテラル | 100(整数) 1.5(浮動小数点数) 0b01(2進数) 0o72(8進数) 0xe1(16進数) |
文字列リテラル | "hoge" |
ルーンリテラル | 'A' |
真偽値リテラル | true, false |
ちなみに、数値リテラルを桁ごとにまとめて表現する方法も用意されていて、とても便利です。
0b0100_1000_0000_0101 // 0b0100100000000101と同じ
0x_67_7a_2f_cc_40_c6 // 0x677a2fcc40c6と同じ
###名前付き定数
名前付きの定数宣言の基本構文はconst 識別子 型 = 式
ですが、その他にも色々な書き方ができます。
参考:https://golang.org/ref/spec#Constant_declarations
// 定数nをint型、数値100で宣言する
const n int = 100
// 定数nを型無し、数値100で宣言する
// 定数の場合は型無しが存在する
const n = 100
// まとめて書くこともできる
const (
n = 100
m = 200
)
###定数式
100+200のように定数から成る演算式を定数式と言います。定数式はコンパイル時に演算が行われます。
種類 | 例 | 演算結果 |
---|---|---|
四則演算 | 100 + 200 | 300 |
シフト演算 | 1 << 2 | 4 |
文字列結合 | "hello," + "world!" | "hello,world!" |
関係演算、論理演算 | 10 == 20 | false |
名前付き定数の宣言時に定数式を用いることもできます。
// 定数nを型無し、数値300で宣言する
// 定数nを定数式で宣言する
const n = 100 + 200
###変数に定数を代入する
定数には型無しが存在しますが、変数には型が存在するため、定数を変数に代入する際に型推論が働きます。
const n = 100 // 定数nを型無し、数値100で宣言する
var a = n // 型推論により変数aをint型で宣言し、100を代入する
###名前付き定数の右辺は省略できる
グループ化された定数宣言の中では、2つ目以降の名前付き定数宣言の右辺を省略することができます。この場合、右辺は1つめの定数宣言の右辺と同じになります。
const (
a = 1
b // b=1
c // c=1
)
iota
を利用すると連続した定数を宣言することができます。iota
はグループ化された定数宣言の中で利用される仕組みで、0から始まり1つずつ加算される値として扱われます。
参考:https://golang.org/ref/spec#Iota
const (
a = iota // iotaの初期値は0
b // b=1
c // c=2
)
グループ化された定数宣言の2つ目以降が1つめの右辺が同じになる特徴と、iota
を組み合わせると、色々な定数宣言ができるようになります。
const (
a = 1 << iota // iotaの初期値は0
b // b=2
c // c=4
)
const (
a = 1 << iota // iotaの初期値は0
b = 1 << iota // b=2(iota=1)
c = 3 // c=3
d = 1 << iota // d=8(iota=3)
)
#制御構文
##条件分岐 if文
if n == 0 {
// 変数nが0と等価なら実行される
}
if n == 0 {
// 変数nが0と等価なら実行される
} else {
// 変数nが0と等価以外なら実行される
}
if n == 0 {
// 変数nが0と等価なら実行される
} else if n > 0 {
// 変数nが0より大きければ実行される
} else {
// それ以外なら実行される
}
if文の場合、条件式の前にステートメントを書くことができる。
if ステートメント; 条件式 {
if a := f(); a == 0 {
// 関数fの返り値を変数aに代入し、aが0と等価なら実行される
} else {
// 変数aが0と等価以外なら実行される
}
###if文の変数スコープについて
if文のステートメントの中で宣言した変数のスコープは、ifとelseのブロック内になります。ブロックは"{"から"}"までの間のことです。
if a := f(); a == 0 {
// ifのブロック
} else {
// elseのブロック
}
else if
の場合、else
の次のif
は次のifブロックになります。次のifブロックもelseブロックに含まれますので、最初のif文のステートメントで宣言した変数のスコープ
if a := f(); a == 0 {
// ifのブロック、aはスコープ内
} else if b := f(); a > 0 && b > 0 {
c := b
// ifのブロック
// a、b、cはスコープ内
} else {
d := b
// elseのブロック
// a、b、dはスコープ内
// cはスコープ外
}
// a、b、c、dはスコープ外
##条件分岐 switch文
Goではswitch文のcase句でbreakを書く必要がありません。また、case句で式が利用できることが特徴です。式が使えるため、if文を並べて書くよりはswitch文を利用した方がスッキリまとめることができます。
switch {
case n == 0: // 式が使える
// 変数nが0の場合に実行される
// breakは不要
case n > 0, n < 10: // 2つ以上の条件を書ける
// 変数nが0より大きい場合に実行される
default: // defaultは書かなくてもいい
// それ以外の場合に実行される
}
caseを跨いで処理をしたい場合はfallthrough
を使います。
switch n {
case 0:
// 変数nが0の場合に実行される
fallthrough
case 1, 2:
// 変数nが0、1、2の場合に実行される
}
#繰り返し for文
Goの繰り返し構文はforしかない(while文は無い)
for文は大きくfor句、単一条件、range句の3つに分類できる。
// for句の利用
// 初期値; 継続条件; 更新文
for i := 0; i < 10; i++ {
}
// 単一条件の利用
// 継続条件
for i < 10 {
}
// range句の利用
// rangeを使ったループ
for i, v = range n {
}
for句や単一条件の利用によるfor文は、初期値、継続条件、更新文を省略することができます。例えば、単一条件の利用で継続条件を省略すると、以下のように無限ループが作れます。
// 何も書かない場合は無限ループ
for {
break // breakで抜け出せる
}
##最後に
今回記事を書くにあたってGoの言語仕様を確認しながら進めることで、より理解も深まったと思います。次回は型と関数についてまとめようと思います。