Golangの基本文法をおさえてみる

http://go-tour-jp.appspot.com/#1
Golangが熱いと小耳に挟んだので読める程度に基本的な文法を抑えていきます。

#Hallo World
```
package main
import("fmt")
func main() {
  fmt.Println("Hallo World")
}
```
開始点：package mainが必要

#型
int：初期値 0
float32: 初期値 0
bool: 初期値 false
string: 初期値 ""
complex64: 初期値 (0+0i)

```
bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // uint8 の別名

rune // int32 の別名
     // Unicode のコードポイントを表す

float32 float64

complex64 complex128
```

#配列
```
p := []int{2, 3, 5, 7, 11, 13}
```

配列のfor文

```
for i := 0; i < len(p); i++ {
  fmt.Printf("p[%d] == %d\n", i, p[i])
}
```

部分配列

```
p[<start>:<end>]
p[1:4]
p[1:]//p[1:<last>]
p[:4]//p[0:4]
```

配列のメモリ確保

```
make([]int, 5) // len(a)=5
make([]int, 0, 5) // len(b)=0, cap(b)=5
```

#Map
```
var m map[string]Vertex
m = make(map[string]Vertex)
```

Mapリテラル
最終行もカンマ必須

```
var m = map[string]int{
    "Bell Labs": 1,
    "Google": 2 ,
}
```
アクセッサ

```
m[key] = elem
elem = m[key]
delete(m, key)
```

キーの有無チェック

```
elem, ok = m[key]//存在すればok=true
```

#変数の宣言
```
var x, y int
```
初期値が与えられた場合、型宣言不要

```
var x, y, z = 0, 0.1, "str"
```
関数内でのみ宣言不要（暗黙的な宣言）

```
func f(){
  x := a
}
```

#定数の宣言
```
const <name> = <val>
```

```
const (
  <name1> = <val1>
  <name2> = <val2>
)
```

#ループ
for文のみ　whileなし

```
for i := 0; i < 10; i++ {
    
}
```

whileと同等

```
for i < 10 {

}
```

無限ループ

```
for {
}
```

要素の繰り返し

```
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
for i, v := range pow {

}
```

indexの破棄

```
for _, v := range pow {

}
```

#条件分岐
```
if x < 0 {

}
```

if文内でのみ有効な変数の宣言

```
if v := math.Pow(x, n); v < lim {
  return v
}
```

else文

```
if v < lim {

} else {
 
}
```
##switch文
自動でbreakする
caseに式が使える

```
    switch time.Saturday {
    case today + 0:
        fmt.Println("Today.")
    case today + 1:
        fmt.Println("Tomorrow.")
    case today + 2:
        fmt.Println("In two days.")
    default:
        fmt.Println("Too far away.")
    }
```

条件のないswitch=if-elseと同等

```
    switch {
    case t.Hour() < 12:
        fmt.Println("Good morning!")
    case t.Hour() < 17:
        fmt.Println("Good afternoon.")
    default:
        fmt.Println("Good evening.")
    }
```



#関数
```
func <method>(<arg> <type>, ...) <type>{}
```

```
func add(x int, y int) int {
    return x + y
}
```
引数が同じ型の場合、最初を省略できる。

```
func add(x, y int) int {
    return x + y
}
```
戻り値を複数返すことが可能

```
func double_string() (string, string){
  return "a", "b"
}
```

戻り値のパラメータ化が可能。
戻り値に名前を付けるとreturn文で明示しなくてよい。

```
func f()(s string){
  s = "aaa"
  return
}
```
変数に代入できる

```
 hypot := func(x, y float64) float64 {
 }
```

Goの関数はクロージャー

```
func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}
```

#構造体
```
type Vertex struct {
    X int
    Y int
}
```
初期化

```
Vertex{1, 2}
```

アクセス

```
v = Vertex{1, 2}
v.X
```

ポインタ

```
 p := Vertex{1, 2}
 q := &p
 q.X
```

フィールドの一部のみ初期化（Name構文）

```
Vertex{X: 1}
```

newを使用した初期化。ポインタが渡される
フィールドは暗黙的な初期化が行われる。

```
var v *Vertex = new(Vertex)
v := new(Vertex)
```

##メソッド
GoにはClassがないが構造体にメソッドをつけられる

```
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
    v := &Vertex{3, 4}
    fmt.Println(v.Abs())
}
```

構造体以外の任意の型も可能

```
type MyFloat float64
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}
f := MyFloat(-math.Sqrt2)
f.Abs()
```

#インターフェース
```
type Abser interface {
    Abs() float64
}
```
実装側でインターフェース名を明示する必要なし

```
type MyFloat float64
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}
var a Abser
a = MyFloat(-math.Sqrt2)
```

#エラーハンドリング
```
type error interface {
    Error() string
}
```

```
type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

func Sqrt(f float64) (float64, error) {}
```

#キャスト
```
z := float64(1)
```


#モジュールのインポート

```
import(
　"module1"
  "moduel2"
)
```

#モジュールのエクスポート
名前を大文字で始める。

* pi:エクスポートされない
* Pi:エクスポートされる

#Web servers
```
package http

type Handler interface {
    ServeHTTP(w ResponseWriter, r *Request)
}
```

```
package main

import (
    "fmt"
    "net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(
    w http.ResponseWriter,
    r *http.Request) {
    fmt.Fprint(w, "Hello!")
}

func main() {
    var h Hello
    http.ListenAndServe("localhost:4000", h)
}
```

#Goroutines
別スレッド実行

```
go f(x, y, z)
```

同期処理（Channels）

```
ch <- v    // v をチャネル ch へ送る。
v := <-ch  // ch から受信し、
           // 変数を v へ割り当てる
```

以上です。マルチスレッディングが文法レベルでサポートされてるのはいいですね。