2. 基本構文
@tenntenn
The Go gopher was designed by Renée French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0 Attributions license.
注意事項と免責事項
2
質問について
3
上田拓也
Go ビギナーズ
Go Conference
@tenntenn
Google Developer Expert (Go)
一般社団法人 Gophers Japan 代表理事
バックエンドエンジニアとして日々Goを書いている。Google Developer Expert (Go)。一般社団法人Gophers Japan代表。Go Conference主催者。大学時代にGoに出会い、それ以来のめり込む。人類をGopherにしたいと考え、Goの普及に取り組んでいる。複数社でGoに関する技術アドバイザーをしている。マスコットのGopherの絵を描くのも好き。
作者
【PR】企業向け研修や技術アドバイザー
2.1. 言語仕様
7
Goの言語仕様
Goの学習と言語仕様
パターン
で学ぶ
ルール
を学ぶ
背景
から学ぶ
初学者
中級者
上級者
どう書くかで学ぶ
未知の書き方に抵抗感
覚える量が増えていく
●
●
●
言語仕様や文法を学ぶ
ルールで未知を克服
リリース後に知る
●
●
●
機能が生まれる背景
リリース前から把握
機能の深い理解が可能
●
●
●
プログラミング言語Go完全入門では
言語仕様や文法にも触れて解説します
Goファイルの構成
package main import "fmt" var msg = "hello" func main() { fmt.Println(msg) fmt.Println("世"+"界") } |
文
式
関数宣言
変数宣言
インポート宣言
パッケージ宣言
他に定数宣言と型宣言がある
英語の文法のようにソースコードが
どのように構成されているか知ろう
宣言(Declarations)
文と式
知識を深める
2.2. 変数
14
変数
15
hoge | 100 |
fuga | true |
piyo | "piyo" |
ここではメモリマップを描いて
メモリ上の状態を把握しやすくしている
変数と型
16
静的型付けの利点
17
変数宣言
18
// 変数宣言と代入が一緒
var n int = 100
// 変数宣言と代入が別
var n int
n = 100
// 型を省略(int型になる)
var n = 100
// varを省略
// 関数内のみでしかできない
n := 100
// まとめる
var (
n = 100
m = 200
)
関数内では
:= で省略する場合が多い
使っていない変数
package main func main() { x := 100 println(x) y := 200 // 使ってないのでコンパイルエラー println(x) // println(y)の間違い } |
組み込み型
20
整数 | int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, byte, rune |
浮動小数点数 | float32, float64 |
複素数 | complex64, complex128 |
文字列 | string |
真偽値 | bool |
インタフェース | error, any, comparable |
組み込みで使える識別子を
宣言済み識別子と呼ぶ
変数のゼロ値
型 | ゼロ値 |
intやfloat64などの数値 | 0 |
string | "" |
bool | false |
errorなどのインタフェース | nil |
変数の利用
Hello, Worldのプログラムをprintln関数に渡す文字列を一度変数に格納してから渡して出力してみよう
22
package main�
func main() {
println("Hello, 世界")
}
2.2. 定数
23
定数
種類 | 例 |
数値リテラル | 100, 1.5 |
文字列リテラル | "hoge" |
ルーンリテラル | 'A', '世' |
2進数・8進数・16進数表記
10進 | 2進 | 8進 | 16進 |
100 | 0b1100100 | 0144 0o144 | 0x64 |
10.5 | - | - | 0x1.5p+03 |
数字の区切り
5_000_000_000_000_000
0b_1010_0110
3.1415_9265
定数式
種類 | 例 | 演算結果 |
四則演算 | 100 + 200 | 300 |
シフト演算 | 1 << 2 | 4 |
文字列結合 | "Hello, " + "世界" | "Hello, 世界" |
関係演算/論理演算 | !(10 == 20) | true |
名前付き定数
// 型のある定数
const n int = 100
// 型のない定数
const m = 100
// 定数式の使用
const s = "Hello, " + "世界"
// まとめる
const (
x = 100
y = 200
)
定数の型
種類 | 型なしの定数 | デフォルトの型 |
整数 | 100 | int |
浮動小数点数 | 1.5 | float64 |
複素数 | 1+4i, complex(0, 4) | complex128 |
ルーン | 'A', '世' | rune |
文字列 | "hoge" | string |
真偽値 | true | bool |
定数のデフォルトの型
package main
func main() {
// 定数は型を持たないので無限の精度になる
const n = 10000000000000000000 / 10000000000000000000
var m = n // mはint型
println(m) // 1
}
なぜ型なしの定数が必要か?
【TRY】定数の利用
Hello, Worldのプログラムをprintln関数に渡す文字列を定数として定義してから出力してください。
32
package main�
func main() {
println("Hello, 世界")
}
右辺の省略
func main() {
const (
a = 1 + 2
b
c
)
fmt.Println(a, b, c)
}
全部3になる
右辺を省略できる
iota
ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) . ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] . |
const ( a, b = iota, iota // 0, 0 c = iota // 1 d, e = iota, iota // 2, 2 ) |
ConstDecl
定数宣言
ConstSpec
0
1
2
定数宣言の文法(EBNF)
iotaを利用した連番
const (
StatusOK = iota // 0
StatusNG // 1(StatusNG = iotaと同じ意味)
)
iotaを利用したフラグ
const (
FlagA = 1 << iota // 1
FlagB // 2 (FlagB = 1 << iotaと同じ意味)
FlagC // 4
FlagD // 8
)
2.4. 演算子
37
算術演算
38
演算子 | 説明 | 利用例 |
+,- | 符号 | +100, -100 |
+ | 加算 | 1+2 |
- | 減算 | 1-1 |
/ | 割り算 | 4/2 |
* | 掛け算 | 3*5 |
% | 余り | 5%2 |
代入演算
39
演算子 | 説明 | 利用例 |
= | 変数への代入 | a = 100 |
:= | 変数の初期化と代入 | a := 100 |
+=,-= など | 演算と代入 | i += 2 |
++ | i += 1と同義 | i++ |
-- | i -= 1と同義 | i-- |
※i++とi--は式ではなく文
ビット演算
40
演算子 | 説明 | 利用例 |
| | 論理和 | 0x10|0x01 |
& | 論理積 | 0x1&0xf |
^ | 否定 | ^0x3 |
^ | 排他的論理和 | 0xc^0x3 |
&^ | 論理積の否定 | 0xc&^0x3 |
<< | 左に算術シフト | 0x1<<4 |
>> | 右に算術シフト | 0x4>>1 |
論理演算
41
演算子 | 説明 | 利用例 |
|| | または | a || b |
&& | かつ | a && b |
! | 否定 | !a |
比較演算
42
演算子 | 説明 | 利用例 |
== | 等しいかどうか | a == b |
!= | 等しくないか | a != b |
< | aはbより小さい | a < b |
<= | aはb以下 | a <= b |
> | aはbより大きい | a > b |
>= | aはb以上 | a >= b |
アドレス演算
43
演算子 | 説明 | 利用例 |
& | ポインタを取得 | &a |
* | ポインタが指す値を取得 | *ptr |
※ポインタ演算はできない
チャネル演算
44
演算子 | 説明 | 利用例 |
<- | チャネルへの送受信 | ch<-100, <-ch |
その他の演算子 ①
45
演算子 | 説明 | 利用例 |
. | フィールドやメソッドのアクセス 参考:https://go.dev/ref/spec#Qualified_identifiers | v.field, v.method() |
[,] | インデクサや型パラメータなど | array[0], slice[10] |
{,} | ブロックやコンポジットリテラルなど | func main() {} |
: | コンポジットリテラルなど | m := map[string]int{ "cat": 100, } |
その他の演算子 ②
46
演算子 | 説明 | 利用例 |
... | 配列リテラルの長さの省略、可変長引数、スライスの展開など | func f(values ...any) { } |
~ |
【TRY】演算子の利用
47
// 整数の演算
n := 100 + 200
// 変数を使った演算
m := n + 100
// 文字列の足し算
msg := "hoge" + "fuga"
2.5. 制御構文
48
if文 ①
49
if x == 1 {
println("xは1")
} else if x == 2 {
println("xは2")
} else {
println("xは1でも2でもない")
}
x == 1
→ true
x == 1
→ false
x == 2
→ true
x == 2
→ false
条件分岐:if
■ Goのifの特徴
50
// ()がいらない
if a == 0 {
}
// できない
if a == 0
{
}
// できない
if (a == 0) fmt.Println(a)
// 代入文を書く�if a := f(); a > 0 {� fmt.Println(a)�} else {� fmt.Println(2*a)�}
aはifとelseの
ブロックで使える
※ Goはコンパイル時に後ろに改行があると、自動でセミコロンを付与する
※ 改行の前が{などの文字だと差し込まない
条件分岐:switch
51
switch a {
case 1, 2:
fmt.Println("a is 1 or 2")
default:
fmt.Println("default")
}
switch {
case a == 1:
fmt.Println("a is 1")
}
caseをまたぐ際には、
fallthroughを使う
何もしないとbreakになる
大量のif-elseをつなぐより
見通しがよくなる
1または2の時
trueを省略している
繰り返し:for
52
// 初期値;継続条件;更新文
for i := 0; i <= 100; i = i + 1 {
}
// 継続条件のみ
for i <= 100 {
}
// 無限ループ
for {
}
// rangeを使った繰り返し
for i, v := range []int{1, 2, 3} {
}
繰り返し:for range
53
// 変数iが0から99まで繰り返し
for i := range 100 { /* 略 */}
// スライス
for i, v := range []int{1, 2, 3} { /* 略 */ }
// マップ
m := map[string]int{"dog": 1, "cat":99}
for k, v := range m { /* 略 */ }
配列・スライス・マップは3. 関数と型を参照。チャネルは9. ゴールーチンとチャネルを参照。
文字列は12. テキスト処理を参照。イテレータは16. イテレータを参照。
break文によるループの抜け出し
54
// breakによる無限ループの脱出
func main() {
var i int
for {
if i%2 == 1 {
break
}
i++
}
}
// ラベル指定のbreak
func main() {
var i int
LOOP: // for文にラベルをつける
for {
switch {
case i%2 == 1:
break LOOP
}
i++
}
}
Goにはgotoも存在する
continueによるループの継続
55
func main() {
var i int
for i := range 10 {
if i%2 == 1 {
continue
}
fmt.Println(i)
}
}
【TRY】奇数と偶数
1-100までの数値のうち、奇数の場合は「数値-奇数」、具偶数の場合は、「数値-偶数」という表示を行うプログラムを作成してください。条件分岐にはifを用いてください。
56
$ go run main.go
1-奇数
2-偶数
3-奇数
4-偶数
...
実行イメージ
switchを使ったパターンもやってみよう
3. 関数と型 👉