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