ENTRANCE

都内でエンジニアやってます。主にRubyとJavaを書いて遊んでる人のブログ。楽しくのんびりとがモットー。

【GO】Golangの勉強を始めたから殴り書きのメモ~その4

つづき。 tour.golang.org

kattsundesu.hatenablog.com

Errors

  • goはエラーをエラー値で表現する。
package main

import (
    "fmt"
    "time"
)

// 構造体
type MyError struct {
    When time.Time
    What string
}

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

func run() error {
    return &MyError{
        time.Now(),
        "it didn't work",
    }
}

func main() {
  // err := run()
  // if err != nil {...} と同意
    if err := run(); err != nil {
        fmt.Println(err)
    }
}

Readers

package main

import (
    "fmt"
    "io"
    "strings"
)

func main() {
    r := strings.NewReader("Hello, Reader!")

    // strings.Readerを作成し、8byte毎に読み出しています。
    b := make([]byte, 8)
    for {
        n, err := r.Read(b)
        fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
        fmt.Printf("b[:n] = %q\n", b[:n])
        // 末端まで行ったらbreak
        if err == io.EOF {
            break
        }
    }
}

Goroutines

  • Goのランタイムに管理される軽量なスレッド
package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    // これでごルーチンが実行される
    go say("world")
    say("hello")
}

Channels

package main

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
  // sumをcに送る
    c <- sum
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    // チャネルを生成する
    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    // チャネルcから値を受け取る
    x, y := <-c, <-c

    fmt.Println(x, y, x+y) // -5 17 12
}
  • Buffered Channels
package main

import "fmt"

func main() {
    // バッファの2ついたチャネルを作成
    // いっぱい渡すとバッファがつまる
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch) // 1
    fmt.Println(<-ch) // 2
}
  • Range and Close
package main

import (
    "fmt"
)

func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        // チャネル
        c <- x
        x, y = y, x+y
    }
    // クローズした後に追加するとpanic
    close(c)
}

func main() {
    // 10のバッファ付きチャネルを作成
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}
  • select
package main

import "fmt"

func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c <- x:
            x, y = y, x+y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    // チャネルを作成
    c := make(chan int)
    // チャネルを作成Part2
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}

/**
0
1
1
2
3
5
8
13
21
34
quit
*/
  • Default Selection
package main

import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            return
        // 何にも該当しなければdefaultに入る
        default:
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
}