LoginSignup
4
3

More than 3 years have passed since last update.

Goを真面目に勉強する〜2.基本構文〜

Last updated at Posted at 2019-12-07

はじめに

Goをはじめて1年半。アウトプットが進まない私が、専門家の@tenntennさんから受けたマンツーマンレッスンの内容をまとめて、Goのスキルアップを目指します。Goの基礎から丁寧に学んでいきます。
記事のまとめは以下の通りで順次作成していきます。
今回は「2.基本構文」になります。

シリーズの一覧

  1. Goについて知っておく事
  2. 基本構文(今回)
  3. 関数と型
  4. パッケージとスコープ

本記事の内容

今回学ぶ内容は以下の通りです。

  • 変数
  • 定数
  • 制御構文
    • 条件分岐
    • 繰り返し

組み込み型

定数、変数を取り扱うにあたって、ここで紹介しておきます。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の言語仕様を確認しながら進めることで、より理解も深まったと思います。次回は型と関数についてまとめようと思います。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3