SlideShare une entreprise Scribd logo
1  sur  35
Télécharger pour lire hors ligne
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言語

Contenu connexe

Tendances

ゲーム向けな美味しい乱数を生成する(再アップ版)
ゲーム向けな美味しい乱数を生成する(再アップ版)ゲーム向けな美味しい乱数を生成する(再アップ版)
ゲーム向けな美味しい乱数を生成する(再アップ版)
ai BlogOnly
 

Tendances (20)

C++20 モジュールの概要 / Introduction to C++ modules (part 1)
C++20 モジュールの概要 / Introduction to C++ modules (part 1)C++20 モジュールの概要 / Introduction to C++ modules (part 1)
C++20 モジュールの概要 / Introduction to C++ modules (part 1)
 
Goでwebアプリを開発してみよう
Goでwebアプリを開発してみようGoでwebアプリを開発してみよう
Goでwebアプリを開発してみよう
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホン
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
 
GAE/GoでWebアプリ開発入門
GAE/GoでWebアプリ開発入門GAE/GoでWebアプリ開発入門
GAE/GoでWebアプリ開発入門
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
 
MRU : Monobit Reliable UDP ~5G世代のモバイルゲームに最適な通信プロトコルを目指して~
MRU : Monobit Reliable UDP ~5G世代のモバイルゲームに最適な通信プロトコルを目指して~MRU : Monobit Reliable UDP ~5G世代のモバイルゲームに最適な通信プロトコルを目指して~
MRU : Monobit Reliable UDP ~5G世代のモバイルゲームに最適な通信プロトコルを目指して~
 
AlmaLinux と Rocky Linux の誕生経緯&比較
AlmaLinux と Rocky Linux の誕生経緯&比較AlmaLinux と Rocky Linux の誕生経緯&比較
AlmaLinux と Rocky Linux の誕生経緯&比較
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
 
ARでVRアバターを表示するシステムを構築しよう
ARでVRアバターを表示するシステムを構築しようARでVRアバターを表示するシステムを構築しよう
ARでVRアバターを表示するシステムを構築しよう
 
ゲーム向けな美味しい乱数を生成する(再アップ版)
ゲーム向けな美味しい乱数を生成する(再アップ版)ゲーム向けな美味しい乱数を生成する(再アップ版)
ゲーム向けな美味しい乱数を生成する(再アップ版)
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
Kotlinアンチパターン
KotlinアンチパターンKotlinアンチパターン
Kotlinアンチパターン
 
【Photon勉強会】1時間でわかるプラグイン開発とその実際(2017/3/23講演)
【Photon勉強会】1時間でわかるプラグイン開発とその実際(2017/3/23講演)【Photon勉強会】1時間でわかるプラグイン開発とその実際(2017/3/23講演)
【Photon勉強会】1時間でわかるプラグイン開発とその実際(2017/3/23講演)
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
Quine・難解プログラミングについて
Quine・難解プログラミングについてQuine・難解プログラミングについて
Quine・難解プログラミングについて
 
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)
 
Go Friday 傑作選
Go Friday 傑作選Go Friday 傑作選
Go Friday 傑作選
 

Similaire à Goroutineと channelから はじめるgo言語 (8)

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

Plus de Takuya Ueda

Plus de Takuya Ueda (20)

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

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