SlideShare a Scribd company logo
Goroutineと
Channelから
はじめるGo言語
ver. 5
2015/11/26(木)
@「最近、Go言語始めました」の会
The Go gopher was designed by Renee French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0
Attributions license.
アジェンダ
● 自己紹介
● Goとは?
● Goroutineの基本
● GoroutineとChannel
● 複数のChannelを扱う
● ファーストクラスオブジェクト
● 単方向のChannel
● for-selectパターン
自己紹介
KLab株式会社
KLabGames事業本部 エンジニア
上田拓也
twitter: @tenntenn
■ 好きな言語
Go, JavaScript, Lua
■ 業務
モバイルオンラインゲームの開発(クライアントサイド)
Goとは?
Googleが開発しているプログラミング言語
■ 特徴
● 並行プログラミング
● 豊富なライブラリ群
● 強力でシンプルな言語設計と文法
● クロスコンパイル/シングルバイナリ
● go tool
Concurrency is not Parallelism
■ ConcurrencyとParallelismは違う
● Concurrency => 並行
● Parallelism => 並列
■ Concurrency
● 同時にいくつかの質の異なる事を扱う
■ Parallelism
● 同時にいくつかの質の同じ事を行う
by Rob Pike
Concurrency is not Parallelism
■ Concurrency
■ Parallelism
本を運ぶ
本を燃やす
台車を運ぶ
本を積む
本を燃やす 本を燃やす 本を燃やす 本を燃やす
ConcurrencyとGoroutine
■ GoroutineでConcurrencyを実現
● 複数のGoroutineで同時に複数のタスクをこなす
● 各Goroutineに役割を与えて分業する
■ 軽量なスレッドのようなもの
● LinuxやUnixのスレッドよりコストが低い
● 1つのスレッドの上で複数のGoroutineが動く
■ Goroutineの作り方
● goキーワードをつけて関数を呼び出す
go fnc()
複数のコアで動くとは限らない
無名関数とGoroutine
package main
import "fmt"
import "time"
func main() {
go func() {
fmt.Println("別のゴールーチン")
}()
fmt.Println("mainゴールーチン")
time.Sleep(50*time.Millisecond)
}
Sleepしないとすぐに終了する
http://play.golang.org/p/jy1HWriRTS
Goroutine-main
Goroutine間のデータのやり取り
Goroutine-2
go f2()
Goroutine-1
go f1()
Goroutine-main
Goroutine間のデータのやり取り
Goroutine-2
go f2()
Goroutine-1
go f1()
変数v
print(v) v = 100
共有の変数を使う?
共有の変数を使う
func main() {
done := false
go func() {
time.Sleep(3 * time.Second)
done = true
}()
for !done {
time.Sleep(time.Millisecond)
}
fmt.Println("done!")
}
共有の変数を使う
http://play.golang.org/p/mGSOaq4mcr
Goroutine-main
Goroutine間のデータのやり取り
Goroutine-2
go f2()
Goroutine-1
go f1()
変数v
print(v) v = 100
処理順序が保証されない!
競合
共有の変数を使う
n := 1
go func() {
for i := 2; i <= 5; i++ {
fmt.Println(n, "*", i)
n *= i
time.Sleep(100)
}
}()
http://play.golang.org/p/yqk82u0E4V
for i := 1; i <= 10; i++ {
fmt.Println(n, "+", i)
n += 1
time.Sleep(100)
}
競合
データ競合の解決方法
■ 問題点
● どのGoroutineが先にアクセスするか分からない
● 値の変更や参照が競合する
■ 解決方法
● 1つの変数には1つのGoroutineからアクセスする
● Channelを使ってGoroutine間で通信をする
● またはロックをとる(syncパッケージ)
"Do not communicate by sharing memory; instead,
share memory by communicating"
Goroutine-main
Channelとは?
Goroutine-2
go f2()
Goroutine-1
go f1()
Channel
100
ch<-100<-ch
Goroutine間でデータの通信
を行うパイプのようなもの
Channelの特徴
■ 送受信できる型
● Channelを定義する際に型を指定する
■ バッファ
● Channelにバッファを持たせることができる
● 初期化時に指定できる
● 指定しないと容量0となる
■ 送受信時の処理のブロック
● 送信時にChannelのバッファが一杯だとブロック
● 受信時にChannel内が空だとブロック
Goroutine-main
送信時のブロック
Goroutine-2
go f2()
Goroutine-1
go f1()
Channel
100
ch<-100
受信してくれるまでブロック
ブロック
Goroutine-main
受信時のブロック
Goroutine-2
go f2()
Goroutine-1
go f1()
Channel
100
<-ch
送信してくれるまでブロック
ブロック
Channelの基本
■ 初期化
■ 送信
■ 受信
ch1 := make(chan int)
ch2 := make(chan int, 10)
ch1 <- 10
ch2 <- 10 + 20
n1 := <-ch1
n2 := <-ch2 + 100
容量を指定
受け取られるまでブロック
一杯であればブロック
送信されまでブロック
空であればブロック
make(chan int, 0)と同じ
Channelの基本
func main() {
done := make(chan bool) // 容量0
go func() {
time.Sleep(time.Second * 3)
done <- true
}()
<-done
fmt.Println("done")
}
送信されるまでブロック
http://play.golang.org/p/k0sMCYe4PA
Goroutine-main
複数のChannelから同時に受信
Goroutine-2
go f2()
Goroutine-1
go f1()
ブロックされるので
同時に送受信出来ない?
Channel-1 Channel-2
ブロック
Goroutine-main
複数のChannelから同時に受信
Goroutine-2
go f2()
Goroutine-1
go f1()
select-caseを使うと
同時に送受信できる
Channel-1 Channel-2
select
select-case
func main() {
ch1 := make(chan int)
ch2 := make(chan string)
go func() { ch1<-100 }()
go func() { ch2<-"hi" }()
select {
case v1 := <-ch1:
fmt.Println(v1)
case v2 := <-ch2:
fmt.Println(v2)
}
}
http://play.golang.org/p/moVwtEdQIv
先に受信した方を処理
nil Channel
func main() {
ch1 := make(chan int)
var ch2 chan string
go func() { ch1<-100 }()
go func() { ch2<-"hi" }()
select {
case v1 := <-ch1:
fmt.Println(v1)
case v2 := <-ch2:
fmt.Println(v2)
}
}
http://play.golang.org/p/UcqW6WH0XT
nilの場合は無視される
ゼロ値はnil
ファーストクラスオブジェクト
■ ファーストクラスオブジェクト
● 変数に入れれる
● 引数に渡す
● 戻り値で返す
● ChannelのChannel
■ timeパッケージ
// 5分間待つ
<-time.After(5 * time.Minute)
http://golang.org/pkg/time/#After
chan chan int など
5分たったら現在時刻が
送られてくるChannelを返す
Channelを引数や戻り値にする
func makeCh() chan int {
return make(chan int)
}
func recvCh(recv chan int) int {
return <-recv
}
func main() {
ch := makeCh()
go func() { ch <- 100 }
fmt.Println(recvCh(ch))
}
http://play.golang.org/p/vg2RhcdNWR
双方向のChannel
func makeCh() chan int {
return make(chan int)
}
func recvCh(recv chan int) int {
go func() { recv <- 200 }()
return <-recv
}
func main() {
ch := makeCh()
go func() { ch <- 100 }()
fmt.Println(recvCh(ch))
}
http://play.golang.org/p/6gU92C6Q2v
間違った使い方ができる
単方向のChannel
func makeCh() chan int {
return make(chan int)
}
func recvCh(recv <-chan int) int {
return <-recv
}
func main() {
ch := makeCh()
go func(ch chan<- int) {ch <- 100}(ch)
fmt.Println(recvCh(ch))
}
http://play.golang.org/p/pY4u1PU3SU
受信専用のChannel
送信専用のChannel
Concurrencyを実現する
■ 複数Goroutineで分業する
● タスクの種類によってGoroutineを作る
● Concurrencyを実現
■ Channelでやりとりする
● Goroutine間はChannelで値を共有する
● 複雑すぎる場合はロックを使うことも
■ for-selectパターン
● Goroutineごとに無限ループを作る
● メインのGoroutineはselectで結果を受信
Goroutine-main
for-selectパターン
Goroutine-2
go f2()
Goroutine-1
go f1()
各Goroutineで
無限ループを作る
Channel-1 Channel-2
select
for{} for{}
つまりこういうこと
Goroutine-1
for{}
Goroutine-2
for{}
Goroutine-3
for{}
Goroutine-4
for{}
Channel
Channel
Channel
Channel
まとめ
■ GoroutineでConcurrencyを実現
● go f()で簡単に作れる
■ Channelでやりとりする
● 送受信時のブロック
● ファーストクラスオブジェクト
● 単方向のChannel
■ for-selectパターン
● Goroutineごとに無限ループを作る
● メインのGoroutineはselectで結果を受信
何か作って発表しよう
■ Go Conferenceに参加しよう
http://eventdots.jp/event/573121
何か作って記事を書こう
■ Go Advent Calendar
● http://qiita.com/advent-calendar/2015/go
● http://qiita.com/advent-calendar/2015/go2
● http://qiita.com/advent-calendar/2015/go3
誰かgo4とgo5を!
Goroutineと channelから はじめるgo言語

More Related Content

PDF
ゲーム開発者のための C++11/C++14
PDF
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
PDF
型安全性入門
PPTX
FINAL FANTASY Record Keeperのマスターデータを支える技術
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け
PDF
できる!並列・並行プログラミング
PPTX
BoostAsioで可読性を求めるのは間違っているだろうか
PDF
Goroutineとchannelから始めるgo言語@初心者向けgolang勉強会2
ゲーム開発者のための C++11/C++14
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
型安全性入門
FINAL FANTASY Record Keeperのマスターデータを支える技術
ネットワーク ゲームにおけるTCPとUDPの使い分け
できる!並列・並行プログラミング
BoostAsioで可読性を求めるのは間違っているだろうか
Goroutineとchannelから始めるgo言語@初心者向けgolang勉強会2

What's hot (20)

PDF
GoによるWebアプリ開発のキホン
PDF
カスタムメモリマネージャと高速なメモリアロケータについて
PPTX
CEDEC2019 大規模モバイルゲーム運用におけるマスタデータ管理事例
PPTX
「書ける」から「できる」になれる! ~Javaメモリ節約ノウハウ話~
PPTX
地理分散DBについて
PDF
Goの時刻に関するテスト
PDF
【Unity】 Behavior TreeでAIを作る
PDF
ソーシャルゲームのためのデータベース設計
PDF
Google Cloud Game Servers 徹底入門 | 第 10 回 Google Cloud INSIDE Games & Apps Online
PDF
MagicOnion入門
PDF
イミュータブルデータモデル(世代編)
PPTX
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
PDF
いまさら聞けない!CUDA高速化入門
PDF
LogbackからLog4j 2への移行によるアプリケーションのスループット改善 ( JJUG CCC 2021 Fall )
PPTX
スマホゲームのチート手法とその対策 [DeNA TechCon 2019]
PDF
新入社員のための大規模ゲーム開発入門 サーバサイド編
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
PPTX
Spanner移行について本気出して考えてみた
PPTX
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
PDF
NumPy闇入門
GoによるWebアプリ開発のキホン
カスタムメモリマネージャと高速なメモリアロケータについて
CEDEC2019 大規模モバイルゲーム運用におけるマスタデータ管理事例
「書ける」から「できる」になれる! ~Javaメモリ節約ノウハウ話~
地理分散DBについて
Goの時刻に関するテスト
【Unity】 Behavior TreeでAIを作る
ソーシャルゲームのためのデータベース設計
Google Cloud Game Servers 徹底入門 | 第 10 回 Google Cloud INSIDE Games & Apps Online
MagicOnion入門
イミュータブルデータモデル(世代編)
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
いまさら聞けない!CUDA高速化入門
LogbackからLog4j 2への移行によるアプリケーションのスループット改善 ( JJUG CCC 2021 Fall )
スマホゲームのチート手法とその対策 [DeNA TechCon 2019]
新入社員のための大規模ゲーム開発入門 サーバサイド編
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Spanner移行について本気出して考えてみた
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
NumPy闇入門
Ad

Similar to Goroutineと channelから はじめるgo言語 (8)

PDF
Goroutineとchannelから始めるgo言語@初心者向けgolang勉強会
PDF
GoでMinecraftっぽいの作る
PDF
オススメの標準・準標準パッケージ20選
PDF
Goでかんたんソースコードの静的解析
PDF
Goとテスト
ODP
Gopenflow demo v1
PDF
Golang入門
PDF
gopherと学ぶgolang ~go fmt編~
Goroutineとchannelから始めるgo言語@初心者向けgolang勉強会
GoでMinecraftっぽいの作る
オススメの標準・準標準パッケージ20選
Goでかんたんソースコードの静的解析
Goとテスト
Gopenflow demo v1
Golang入門
gopherと学ぶgolang ~go fmt編~
Ad

More from Takuya Ueda (20)

PDF
Goにおけるバージョン管理の必要性 − vgoについて −
PDF
WebAssembly with Go
PDF
GAE/Goとsyncパッケージ
PDF
静的解析を使った開発ツールの開発
PDF
そうだ、Goを始めよう
PDF
マスター・オブ・goパッケージ
PDF
メルカリ カウルのマスタデータの更新
PDF
Go1.8 for Google App Engine
PDF
Go Friday 傑作選
PDF
GoによるiOSアプリの開発
PDF
Static Analysis in Go
PDF
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
PDF
メルカリ・ソウゾウでは どうGoを活用しているのか?
PDF
エキスパートGo
PDF
Go静的解析ハンズオン
PDF
Goにおける静的解析と製品開発への応用
PDF
Gopher Fest 2017参加レポート
PDF
Google Assistant関係のセッションまとめ
PDF
Cloud functionsの紹介
PDF
goパッケージで型情報を用いたソースコード検索を実現する
Goにおけるバージョン管理の必要性 − vgoについて −
WebAssembly with Go
GAE/Goとsyncパッケージ
静的解析を使った開発ツールの開発
そうだ、Goを始めよう
マスター・オブ・goパッケージ
メルカリ カウルのマスタデータの更新
Go1.8 for Google App Engine
Go Friday 傑作選
GoによるiOSアプリの開発
Static Analysis in Go
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
メルカリ・ソウゾウでは どうGoを活用しているのか?
エキスパートGo
Go静的解析ハンズオン
Goにおける静的解析と製品開発への応用
Gopher Fest 2017参加レポート
Google Assistant関係のセッションまとめ
Cloud functionsの紹介
goパッケージで型情報を用いたソースコード検索を実現する

Goroutineと channelから はじめるgo言語