post Image
Goのchannelの送受信用の型について

初めに

Goにはchannelと呼ばれる、並行処理用のキューがあります。
基本的なことは他の記事に譲るとして、
これを使うと簡単に同期的にキューが扱え、ブロッキングもしてくれるので並行同期処理をする場合に(Javaなどに比べ)かなり楽に書けます。

channelの例

標準のchannel
// 容量10のchannel作成
c := make(chan int, 10)

// キューに送信
c <- 10

// キューから受信し、値を出力
// キューに値がなければデッドロッグ
fmt.Println(<-c) //10

実は、channelには送信専用・受信専用の型(?)があります。
Effective Go
https://golang.org/doc/effective_go.html#channels
や記事などにもあまり書かれてないので
記載したいと思います。

送信専用のchannel

(コンパイルエラーになります。)

送信専用のchannel
// 送信専用の容量10のchannel作成
c := make(chan<- int, 10)

// キューに送信
c <- 10

// 送信専用なのでコンパイルエラーになる。
fmt.Println(<-c)

受信専用のchannel

(コンパイルエラーになります。)

受信専用のchannel
// 受信専用の容量10のchannel作成
c := make(<-chan int, 10)

// 受信専用なのでコンパイルエラー
c <- 10

fmt.Println(<-c) 

使いどころ

上だけ見ると、コンパイルエラーになるので使いどころあるの?という感じですが。

実は、
「標準のchannel型」 → 「入力 or 出力専用のchannel型」
への代入ができます。

(それ以外はできないようです。)

うまく使うと型レベルで宣言し、コンパイル時にチェックできます。

channelの代入
package main

import (
    "fmt"
)

func main() {
    c := make(chan int, 10)
    c2 := make(chan<- int, 10)

    c2 = c

    // c2に4を送信する
    c2 <- 4

    // c2は送信専用なのでコンパイルエラー 
//  fmt.Println(<-c2)   

    // cからを受信すると4を受け取れる
    fmt.Println(<-c)
}

これだけだと、あまり大したことないですが、以下の様に関数呼び出しで使う場面もでてくるかもしれません。

送信専用のchannelの使用例

go tourの非同期的なfibonacciの例ですが
https://go-tour-jp.appspot.com/#66

このfibonacci関数内では、channelに対して送信しかしておりません。
なので

fibonacchi(送信Only)
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
    }
    close(c)
}

func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}

と書くことが出来ます。
http://play.golang.org/p/4YtIDSDGkS

これでfibonacci関数内で送信しかしないと明示でき、
間違えて受信の処理をしてしまうことを防げます。

受信専用のchannelの使用例

非同期に素数を順番にジェネレートする関数です。
呼び出した側は、受信のみにさせることが出来ます。

素因数分解のジェネレータ(受信Only)
package main

import (
    "fmt"
)

func getPrimeGen() <-chan int {
    var gen = make(chan int)
    go func() {
        var primes = make([]int, 0)
        for k := 2; ; k++ {
            check := true
            for _, value := range primes {
                if k % value == 0 {
                    check = false
                    break
                }
            }
            if check {
                primes = append(primes, k)
                gen <- k
            }
        }
        close(gen)
    }()
    return gen
}

func main() {
    //受け取ったchannelは受信のみ
    primeGen := getPrimeGen()

    for i := 0; i < 10000-1; i++ {
        <-primeGen
    }
    // 素数の10000番目を出力します。
    fmt.Println(<-primeGen)

}

http://play.golang.org/p/UVk5Z5U266

まとめ

channelの送受信用のchannel型もうまく使っていきましょう。


『 Go 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。