Goの基本のキ
Tour of Goの内容メモ
手元に実行環境も用意しているが、オンラインでも用意されているのはありがたい。
Imports | パッケージの参照
import "fmt"
import (
"fmt"
"math/rand"
)
Functions | 関数
func add(x int, y int) int {
return x + y
}
引数となる変数名の後ろに型名を書く。
同じ型の引数が複数ある場合は、最後の型を省略する記述が可能。
func add(x, y int) int {
return x + y
}
関数は複数の戻り値を返すこともできる
func swap(x, y string) (string, string) {
return y,x
}
戻り値となる変数に名前を付けることも可能(named return value)
戻り値に名前を付けると、関数の最初で定義した変数名として扱われる。
また、名前を付けた戻り値を使うと、 return
ステートメントに何も書かずに戻すことが可能。(これを naked returnと呼ぶ)
naked return は、短い関数でのみ利用すべきらしい。長い関数で使うと可読性が悪くなるため非推奨。
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
Variable | 変数
変数の宣言には var
ステートメントを使用する。
var c, python, java bool
func main() {
var i int
fmt.PrintLn(i, c, python, java)
}
初期化も行う場合、型を省略することができる。その変数は初期化子が持つ型と同じになる。
var i, j int = 1, 2
var c, python, java = true, false, "no"
関数の中でのみ、省略形 :=
の代入文を使って、型宣言が可能。
func main() {
var i, j int = 1, 2
k := 3
c, python, java := true, false, "no!"
...
}
Basic Types | Goの基本の型
- bool
- string
- int, int8, int16, int32, int64
- uint, uint8, uint16, uint32, uint64, uintptr
- byte (uint8の別名)
- rune (int32の別名。Unicodeのコードポイントを表す)
- float32, float64
- complex64, complex128
int
, uint
, uintptr
型は32-bitシステムでは32bit, 64-bitシステムでは64bitで扱われる。
特別な理由がない限り、整数の変数が必要な場合は int
で良い。
変数に初期値を与えずに宣言するとゼロ値が与えらられる。
- 数値型の場合(int, float):
0
- bool型:
false
- string型:
""
(空文字列)
Type Conversions | 型変換
変数 v
を 型 T
に変換したい場合、T(v)
と記述することで変換ができる。
var i int = 42
var f float64 = float64(i)
var u int = uint(f)
C言語とは異なり、明示的な変換が必要。
明示的に変換せずに別の型の変数に代入しようとすると、以下のようなエラーが表示される。
package main
import (
"fmt"
)
func main() {
var i int = 42
var f float64 = i
fmt.Println(i,f)
}
> ./prog.go:9:18: cannot use i (variable of type int) as type float64 in variable declaration
Constants | 定数
Goで定数を扱いたい場合は、 const
キーワードを使用する。
定数は、文字(character)、文字列(string)、boolean、数値(numeric)のみ使える。
また、定数は :=
を使って宣言することはできない。
const World = "世界"
const Truth = true
For
for
ループは、初期化、条件式、後処理をセミコロンで区切って記述する。
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
初期化と後処理は任意。書かなくても動作する。
func main() {
sum := 1
for ; sum < 1000; {
sum += sum
}
fmt.Println(sum)
}
セミコロンを省略することもできる。この書き方で while
文のような使い方が可能。
func main() {
sum := 1
for sum < 1000 {
sum += sum
}
fmt.PrintLn(sum)
}
他の言語のように、条件部分を()
で括る必要はない。括るとシンタックスエラーになる。
また、初期化の際に var
を使った初期化は行えない。:=
を使用する必要がある。
ループ条件を省略すれば、無限ループになる。
func main() {
for {
}
}
If
for
と同様に括弧は不要。
func sqrt(x float64) string {
if x < 0 {
return sqrt(-x) + "i"
}
return fmt.Sprint(math.Sqrt(x))
}
if
ステートメントは、条件の前に、簡単なステートメントを書くことができる。
下の例では変数v
が宣言されている。このv
はif
のスコープ内だけで使用できる。
if
のスコープ外では v
は使えない。
func sum2(x, y, limit int) int {
if v := x + y; v < limit {
return v
}
return 0
}
func main() {
fmt.Println(
sum2(1,2,10),
)
}
> 3
if
と else
の書き方
func sum3(x, y, limit int) int {
if v := x + y; v < limit {
return v
} else {
return v+1
}
return 0
}
if
ステートメントで宣言された変数は、else
ブロックでも使用することができる。
Switch
switch
ステートメントは、if-else
ステートメントのシーケンスを短く方法。
Goのswitchは、選択されたcaseだけを実行して、それに続く他の全てのcaseは実行されない。
他の言語では、caseの最後に必要な break
ステートメントがGoでは不要になる。(自動的に提供される)
breakを明示的に記述してもエラーは起きず、実行可能。
また、Goのswitchのcaseは定数や整数である必要がない。
func choice(name string) {
switch s := name; s {
case "apple":
fmt.Println("apple select")
case "banana":
fmt.Println("banana select")
case "orange":
fmt.Println("orange select")
default:
fmt.Println("no select")
}
}
switchは、上から下へと評価される。caseの条件が一致すれば、そこで終了する。
条件のないswitchは switch true
と書くことと同じ。
この構造により、if-then-else
をシンプルに表現することができる。
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
余談だがTour of Goでは、switchステートメントとcaseステートメントのインデントが同じ階層にある。もちろん実行可能だが、caseステートメントはswitchの {}
の中で使われてるのでインデントさせたほうが気持ちがいい。インデントしてもエラーなく動作する。
Defer
defer
ステートメントは、defer
へ渡した関数の実行を、呼び出し元の関数の終わり(returnする)まで遅延させる。
defer
へ渡した関数の引数は、すぐに評価されるが、その関数自体は呼び出し元の関数がreturnするまで実行されない。
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
> hello
> world
defer
へ渡した関数が複数ある場合はスタックされる。渡された関数はLIFO(最後に入れたものが最初に出る)の順番で実行される。
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
> counting
> done
> 9
> 8
> 7
> 6
> 5
> 4
> 3
> 2
> 1
> 0
defer
のより詳細な使い方は、こちらの記事に誘導されていた。
Discussion