言語仕様
字句、リテラル
予約語
https://golang.org/ref/spec#Keywords
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
文字列
https://golang.org/ref/spec#String_literals
`foo`
… raw string literal. ヒアドキュメントのように使える。
Examples:
help := `Usage:
hogehoge
fugafuga
`
fmt.Println(help)
rune
https://golang.org/ref/spec#Rune_literals
int32のaliasで、Unicode文字を扱うためのもの。
'x'
, '\n'
のように、シングルクォートで囲んで表現する。
参考:
変数
https://golang.org/ref/spec#Variables
Examples:
// 型が同じものをまとめて宣言
var c, python, java bool
// 宣言と同時に初期化
var i, j int = 1, 2
定数
Examples:
const (
Pi = 3.14
Big = 1 << 100
)
- 文字(character)、文字列(string)、boolean、数値(numeric)のみで使える
:=
を使って宣言できない- 数値の定数は高精度な値。intの上限を越える値も保持できる
iota
https://golang.org/ref/spec#Iota
0から始まる連番の整数値を生成できる。
Examples:
const (
// 定数宣言で右辺を省略すると直前と同じ式が使われる
c0 = iota // c0 == 0
c1 // c1 == 1
c2 // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota == 0)
b // b == 2 (iota == 1)
c = 3 // c == 3 (iota == 2, unused)
d = 1 << iota // d == 8 (iota == 3)
)
const (
u = iota * 42 // u == 0 (untyped integer constant)
v float64 = iota * 42 // v == 42.0 (float64 constant)
w // w == 84 (untyped integer constant)
)
const x = iota // x == 0
const y = iota // y == 0
関連項目:
参考:
変数のエクスポート
https://golang.org/ref/spec#Exported_identifiers
package foo
var privateVar string = "this is private" // パッケージ外から見えない
var PublicVar string = "this is public" // パッケージ外から見える
// パッケージ外から見える
type Person struct {
Name string // パッケージ外から見える
age int // パッケージ外から見えない
}
// パッケージ外から見えない
type ninja struct {
skill *Skill
hp int
}
参考:
ゼロ値
変数に初期値を与えずに宣言すると、ゼロ値が与えられる。
型によって以下のようになる:
- 数値型(int, floatなど):
0
- bool型:
false
- string型: "" (空文字列)
- スライス:
[]
(空スライス) - map:
nil
- 構造体:
{}
(空の構造体) - ポインタ型:
nil
- 関数型:
nil
真偽判定
真偽判定(ifの条件式)に使えるのはbool型の値のみのようだ。
LLみたいに数値や文字列を真偽判定に用いることはできない。
true //=> true
false //=> false
s := ""
if s { //=> エラー。文字列は判定できない
:
}
len(s) > 0 //=> false
s == "" //=> true
i := 1
if i { //=> エラー。数値は判定できない
:
}
参考:
制御構文
switch
https://golang.org/ref/spec#Switch_statements
Examples:
switch tag {
default: s3()
case 0, 1, 2, 3: s1()
case 4, 5, 6, 7: s2()
}
switch x := f(); { // missing switch expression means "true"
case x < 0: return -x
default: return x
}
switch {
case x < y: f1()
case x < z: f2()
case x == 4: f3()
}
// 型で分岐
var i interface{}
i = 100
switch v := i.(type) {
case int:
fmt.Println(v*2)
case string:
fmt.Println(v+"hoge")
default:
fmt.Println("default")
}
参考:
ループ
https://golang.org/ref/spec#For_statements
for
しかない
Examples:
for {
// 無限ループ
}
for i := 1; i < 100; i++ {
// iが[1, 100)の間
}
// collection要素のイテレーション
dayOfWeeks := [...]string{"月", "火", "水", "木", "金", "土", "日"}
for arrayIndex, dayOfWeek := range dayOfWeeks {
fmt.Printf("%d番目の曜日は%s曜日です。\n", arrayIndex + 1, dayOfWeek)
}
※mapをイテレーションする場合、取り出し順はランダムになる。
参考:
ラベル
大域脱出や、gotoで使える。
Examples:
OuterLoop:
for {
for {
break OuterLoop
}
if someCondition {
goto End
}
}
Switch:
switch x {
case y:
for {
break Switch
}
}
End:
os.Exit(0)
関数
https://golang.org/ref/spec#Function_types
シグネチャの例:
func()
func(x int) int
// 連続する複数の引数の型が同じときは、最後の型以外を省略できる
func(a, _ int, z float32) bool
func(a, b int, z float32) (bool)
func(prefix string, values ...int)
func(a, b int, z float64, opt ...interface{}) (success bool)
func(int, int, float64) (float64, *[]int)
func(n int) func(p *T)
入門ガイド:
Limitation:
- Rubyとかにあるような引数にデフォルト値を与えるような仕様はない
- 構造体を使って似たようなことはできる。下の参考に挙げたリンク先を参照
参考:
無名関数(クロージャ)
https://golang.org/ref/spec#Function_literals
f := func(x, y int) int { return x + y }
可変長引数
https://golang.org/ref/spec#Passing_arguments_to_..._parameters
ある関数の最後の引数 p
が ...T
と記述されたなら、 p
の型は []T
である。
呼び出し側が p
に何も与えなかった場合、 p
は nil
となる。
Examples:
func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")
呼び出し側はスライス変数sを使って s...
のように記述できる。
Examples:
s := []string{"James", "Jasmine"}
Greeting("goodbye:", s...)
参考:
メソッド
https://golang.org/ref/spec#Method_declarations
レシーバのある関数。
Examples:
func (p *Point) Length() float64 {
return math.Sqrt(p.x * p.x + p.y * p.y)
}
func (p *Point) Scale(factor float64) {
p.x *= factor
p.y *= factor
}
- レシーバの型は
type
で定義された型か、そのポインタ(基底型と呼ばれる) - レシーバ型はポインタやインタフェースであってはならない
- レシーバ型はメソッドと同じパッケージで定義されなければならない
メソッドの型は、レシーバを第1引数とする関数。
例えば、上述の Scale
は次の型を持つ:
func(p *Point, factor float64)
ただし、この形式で宣言された関数はメソッドではない。
式
セレクタ
https://golang.org/ref/spec#Selectors
レシーバがパッケージ名以外のもので .
でアクセスされるもの。
構造体のメンバ変数かメソッドを指すことが多い。
文
defer
https://golang.org/ref/spec#Defer_statements
入門ガイド:
ある関数の中で defer 関数
の形式で書かれる。
当該関数から return
する前に、deferで指定された関数が確実に実行される。
エラー発生時のclean up処理などに用いられる。
Examples:
lock(l)
defer unlock(l) // unlocking happens before surrounding function returns
// prints 3 2 1 0 before surrounding function returns
for i := 0; i <= 3; i++ {
defer fmt.Print(i)
}
// f returns 42
func f() (result int) {
defer func() {
// result is accessed after it was set to 6 by the return statement
result *= 7
}()
return 6
}
レキシカルスコープ
https://golang.org/ref/spec#Declarations_and_scope
- Goのコードは、ブロックによるレキシカルスコープを持つ
- ブロックで宣言された識別子は、内部ブロックで再宣言できる
- 内部で宣言された識別子のスコープは内部ブロックに閉じる
Examples:
https://play.golang.org/p/HOmvzO1l1qc
s := "main scope"
{
s := "inner scope"
fmt.Printf("Hello, %s\n", s)
}
fmt.Printf("Hello, %s\n", s)
実行結果:
Hello, inner scope
Hello, main scope
参考:
ブロック
https://golang.org/ref/spec#Blocks
上のように { ... }
でブロックを作れる。
Perlっぽい。
Spec:
- packageはpackage blockを持つ
- if, for, switchなんかも自身のブロックを持つ。
- ブロックはネストできる
日付・時刻
日時フォーマット
Go言語の日時のフォーマット関数(timeパッケージのfunc (Time) Format))に与えられる引数は、2006-01-02T15:04:05(月曜)の日時となっている。
これはアメリカで時刻を表記する際の順番で、1月2日午後3時4分5秒2006年となり、わかりやすかったからだそうだ。
参考:
goroutine
OSのネイティブスレッドより扱いやすくしたもの。
スレッドとファイバーの良いとこ取り。
go
というキーワードを付けるとgoroutineが作られる。
Examples:
// 別のgoroutineを作って既存関数を実行
go Function()
// 別のgoroutineを作って、無名関数を実行
go func() {
// goroutine内で実行したい処理
}
参考:
チャネル
SYNOPSIS:
// バッファなし
tasks := make(chan string)
// バッファ付き
tasks := make(chan string, 10)
// データ送信
tasks <- "cmake .."
tasks <- "cmake . --build Debug"
// データ受信
task := <-tasks
// データ受信 + クローズ判定
task, ok := <-tasks
// データを読み捨てる
<-wait
Examples:
select文
複数のチャネルを待機する場合に使う。
Examples:
// ブロックせずに受信し、かつ、チャネルがクローズ済みかどうかチェックする
select {
case v, ok := <- ch:
if ok {
fmt.Println(v)
} else {
fmt.Println("closed")
}
default:
fmt.Println("no value")
}
// ブロックせずに送信
select {
case ch <- v:
fmt.Println("sent")
default:
fmt.Println("no capacity")
}
参考:
ビルトイン関数
append
https://golang.org/pkg/builtin/#append
func append(slice []Type, elems ...Type) []Type
sliceに要素、またはsliceを結合し、新たなsliceを返す。
slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)
panic
https://golang.org/pkg/builtin/#panic
func panic(v interface{})
Examples:
panic("a problem")
_, err := os.Create("/tmp/file")
if err != nil {
panic(err)
}
関連項目:
パッケージ
import
https://golang.org/ref/spec#Import_declarations
Examples:
import (
"fmt"
. "math" // Exportされた関数等を自パッケージのもののように使える
s "strings" // sとしてimport
_ "testing" // importするけど使わない
)
構文:
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
参考:
import cycle not allowed
相互import, 循環importはNG.
コンパイルエラーになる。
参考:
init()関数による初期化
- ソースファイルに1つ
func init()
を記述できる - ソースファイル読み込み時に1回実行される
- importされるpackageのinit()が先に実行される
- pがqをimportしているとき、pのinit()より先にqのinit()が完了している
- mainパッケージのinit()が最後に実行される
参考: