SlideShare a Scribd company logo
1 of 77
Download to read offline
Goらしい
APIを求める旅路
GoCon 2018 Spring Apr 15 2018
Daisuke Maki @lestrrat (HDE inc)
• @lestrrat
• Perl/Go hacker, author, father
• Author of github.com/peco/peco
• Organizer for builderscon
<宣伝>
http://blog.builderscon.io/entry/call-for-sponsors-2018
スポンサー募集、今月末まで!
お題
「Goっぽい」コード
Goを使うなら
なるたけGoっぽいAPIがいい
Goを使うなら
なるたけGoっぽいAPIがいい
github.com/cenkalti/backoff
backoff.Retry(f, strategy)
github.com/cenkalti/backoff
backoff.Retry(f, strategy)
[func() error]
Callback/Closure
• 関数を受け取るAPIでは、シグネチャがポイ
ントになる
• 関数を許すからにはadhocな関数呼び出しが
できるべき
net/http
type HandleFunc func(ResponseWriter, *Request)
• net/httpでこの関数の副作用は気にしない
でよい
• AdhocなHandlerをポンポン登録できる
backoff.Retry(f, stretegy)
func Foo() (Result, Result, Result, error)
What About…
backoff.Retry(Foo, …)
This no worky…
backoff.Retry(Foo, …)
This no worky…
signatureが合わない
backoff.Retry(func() error {
a, b, c, err := Foo()
if err != nil {
return err
}
}, …)
Capture Return Values
backoff.Retry(func() error {
a, b, c, err := Foo()
if err != nil {
return err
}
}, …)
Capture Return Values
この戻り値をRetryの外側で使うには?
var a, b, c Result
backoff.Retry(func() error {
a, b, c, err := Foo()
if err != nil {
return err
}
}, …)
Upper Scope
var a, b, c Result
backoff.Retry(func() error {
a, b, c, err := Foo()
if err != nil {
return err
}
}, …)
Upper Scope
あ!
var a, b, c Result
backoff.Retry(func() error {
a, b, c, err = Foo()
if err != nil {
return err
}
}, …)
Final Result
ちょっとまった!
• スコープを気にしながらコードを書かな
いといけない
• := と = を間違ってもコンパイラが怒っ
てくれない
• 毎回ムダ?にクロージャを作ってて
どんなAPIだと ?
+
拡張性を持たせられる?
Use Interface?
backoff.Retry(f, stretegy)
Use Interface?
backoff.Retry(f, stretegy)
type Operation interface {
Do() error
}
type FooWrapper struct {
A Result
B Result
C Result
}
func (f *FooWrapper) Do() error {
f.A, f.B, f.C, err = Foo()
…
}
Store The Results
var f FooWrapper
backoff.Retry(f, …)
// Use f.A, f.B, f.C
Final Result
var f FooWrapper
backoff.Retry(f, …)
// Use f.A, f.B, f.C
Final Result
「これじゃない感」…
毎回型を作る必要がある…
たとえばadhocな関数は?
type OperationFunc func() error
func (f OperationFunc) Do() error {
return f()
}
Adhoc Functions?
type OperationFunc func() error
func (f OperationFunc) Do() error {
return f()
}
Adhoc Functions?
http.HandlerFuncと同じ
形にすればキレイになる?
var a, b, c Result
backoff.Retry(OperationFunc(func() error {
a, b, c, err = Foo()
if err != nil {
return err
}
}), …)
あ、これ前と同じだ
小細工では同じような形に
なってしまう
一歩引いて考え直す…
backoffは何をするのか
• 関数を実行する
• 成功したら終わる
• 失敗したら、待つ
• optional: context.Contextで途中停止
for {
if err := f(); err == nil {
return
}
time.Sleep(delay)
}
First pass
for {
if err := f(); err == nil {
return
}
time.Sleep(delay)
}
First pass
関数を実行する
成功したら終わる
失敗したら待つ
backoffは何をするのか
• 関数を実行する
• 成功したら終わる
• 失敗したら、待ち時間を増やしながら待つ
• optional: context.Contextで途中停止
for {
if err := f(); err == nil {
return
}
select {
case <-ctx.Done():
return
case <-time.After(nextDelay()):
}
}
Second pass
for {
if err := f(); err == nil {
return
}
select {
case <-ctx.Done():
return
case <-time.After(nextDelay()):
}
}
Second pass
関数を実行する
成功したら終わる
for {
if err := f(); err == nil {
return
}
select {
case <-ctx.Done():
return
case <-time.After(nextDelay()):
}
}
Second pass
関数を実行する
成功したら終わる
失敗したら待ち時間を
増やしながら待つ
context.Contextで
途中停止
この形を簡単に書けるように
すればいいはず…
github.com/lestrrat-go/backoff
policy := backoff.NewExponential(…)
Backoff Policy Object
b, cancel := policy.Start(ctx)
Backoff object
b, cancel := policy.Start(ctx)
defer cancel()
for {
if err := f(); err == nil {
return
}
select {
case <-b.Done():
return
case <-b.Next():
}
}
b, cancel := policy.Start(ctx)
defer cancel()
for {
if err := f(); err == nil {
return
}
select {
case <-b.Done():
return
case <-b.Next():
}
}
<-chan time.Time
<-chan struct{}
ただのコードブロックなので
戻り値も自由自在
b, cancel := policy.Start(ctx)
defer cancel()
for {
a, b, c, err := f()
if err == nil {
// use or return a, b, c here
}
select {
case <-b.Done():
return
case <-b.Next():
}
}
b, cancel := policy.Start(ctx)
defer cancel()
for {
a, b, c, err := f()
if err == nil {
// use or return a, b, c here
}
select {
case <-b.Done():
return
case <-b.Next():
}
}
Bonus: separate Policy/Backoff
b := cenkalti.NewExponential()
for … {
go func(b cenkalti.Backoff) {
// b is shared… be careful!
}(b)
}
bを共有せざるを得ない
for … {
go func(b backoff.Backoff, cancel func()) {
// b is safe to be used in a separate goroutine
}(policy.Start(ctx))
}
共有されるpolicyとbは別
Problem:
Boilerplate Code is Long
b, cancel := policy.Start(ctx)
defer cancel()
for {
a, b, c, err := f()
if err == nil {
return
}
select {
case <-b.Done():
return
case <-b.Next():
}
}
b, cancel := policy.Start(ctx)
defer cancel()
for {
a, b, c, err := f()
if err == nil {
return
}
select {
case <-b.Done():
return
case <-b.Next():
}
}
for {
select {
case <-b.Done():
return
case <-b.Next():
}
}
for {
select {
case <-b.Done():
return
case <-b.Next():
}
}
for {
select {
case <-b.Done():
return
case <-b.Next():
}
}
bail out of loop
for {
select {
case <-b.Done():
return
case <-b.Next():
}
}
bail out of loop
continue loop
これ、Loop Condition だ
func Continue(b *Backoff) bool {
select {
case <-b.Done():
return false
case <-b.Next():
return true
}
return false // never reached
}
func to determine loop condition
b, cancel := policy.Start(ctx)
defer cancel()
for backoff.Continue(b) {
a, b, c, err := f()
if err == nil {
return
}
}
キュッとした!
b, cancel := policy.Start(ctx)
defer cancel()
for backoff.Continue(b) {
a, b, c, err := f()
if err == nil {
return
}
}
キュッとした!
use as condition
確認
確認
contextで途中停止
確認
channelでタイミング制御
contextで途中停止
確認
channelでタイミング制御
for backoff.Continue() でループ制御
contextで途中停止
確認
channelでタイミング制御
for backoff.Continue() でループ制御
contextで途中停止
goroutine safe by design
確認
クロージャに頼る必要がない
channelでタイミング制御
for backoff.Continue() でループ制御
contextで途中停止
goroutine safe by design
APIデザインをする時はその言
語の自然なフローを許す形を
考えるのがお勧め
(なお、コードをよく読むと、
cenkalti/backoffも実装はほぼ同じ仕
組みになっているが、公開しているイ
ンターフェースがまったく違う)
おまけ
「Google APIから学ぶ自動生成」
※ Goの連載記事です
※ GoのためのAPIデザインの話です
End

More Related Content

What's hot

20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
イミュータブルデータモデルの極意
イミュータブルデータモデルの極意イミュータブルデータモデルの極意
イミュータブルデータモデルの極意Yoshitaka Kawashima
 
InnoDBのすゝめ(仮)
InnoDBのすゝめ(仮)InnoDBのすゝめ(仮)
InnoDBのすゝめ(仮)Takanori Sejima
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編infinite_loop
 
5分で出来る!イケてるconfluenceページ
5分で出来る!イケてるconfluenceページ5分で出来る!イケてるconfluenceページ
5分で出来る!イケてるconfluenceページCLARA ONLINE, Inc.
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Etsuji Nakai
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -onozaty
 
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)NTT DATA Technology & Innovation
 
BuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドBuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドAkihiro Suda
 
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)Mikiya Okuno
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるpospome
 
ビッグデータ処理データベースの全体像と使い分け
ビッグデータ処理データベースの全体像と使い分けビッグデータ処理データベースの全体像と使い分け
ビッグデータ処理データベースの全体像と使い分けRecruit Technologies
 
ソーシャルゲーム案件におけるDB分割のPHP実装
ソーシャルゲーム案件におけるDB分割のPHP実装ソーシャルゲーム案件におけるDB分割のPHP実装
ソーシャルゲーム案件におけるDB分割のPHP実装infinite_loop
 
ファイルシステム比較
ファイルシステム比較ファイルシステム比較
ファイルシステム比較NaoyaFukuda
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Taku Miyakawa
 
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)NTT DATA Technology & Innovation
 
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?naoki koyama
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎信之 岩永
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法Tetsutaro Watanabe
 

What's hot (20)

20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
イミュータブルデータモデルの極意
イミュータブルデータモデルの極意イミュータブルデータモデルの極意
イミュータブルデータモデルの極意
 
InnoDBのすゝめ(仮)
InnoDBのすゝめ(仮)InnoDBのすゝめ(仮)
InnoDBのすゝめ(仮)
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編
 
5分で出来る!イケてるconfluenceページ
5分で出来る!イケてるconfluenceページ5分で出来る!イケてるconfluenceページ
5分で出来る!イケてるconfluenceページ
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
 
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
 
BuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドBuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルド
 
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
 
ビッグデータ処理データベースの全体像と使い分け
ビッグデータ処理データベースの全体像と使い分けビッグデータ処理データベースの全体像と使い分け
ビッグデータ処理データベースの全体像と使い分け
 
ソーシャルゲーム案件におけるDB分割のPHP実装
ソーシャルゲーム案件におけるDB分割のPHP実装ソーシャルゲーム案件におけるDB分割のPHP実装
ソーシャルゲーム案件におけるDB分割のPHP実装
 
ファイルシステム比較
ファイルシステム比較ファイルシステム比較
ファイルシステム比較
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)
 
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 

Similar to GoらしいAPIを求める旅路 (Go Conference 2018 Spring)

C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいdigitalghost
 
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPAkira Takahashi
 
明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理Yuto Matsukubo
 
AOSPをミラーしてみた
AOSPをミラーしてみたAOSPをミラーしてみた
AOSPをミラーしてみたkinneko
 
基礎からC言語 part1
基礎からC言語 part1基礎からC言語 part1
基礎からC言語 part1Hiroyuki Ito
 
FuelPHPをさわってみて
FuelPHPをさわってみてFuelPHPをさわってみて
FuelPHPをさわってみてSotaro Omura
 
第2回デザインパターン資料
第2回デザインパターン資料第2回デザインパターン資料
第2回デザインパターン資料gaaupp
 
Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2
Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2
Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2Preferred Networks
 
Let’s translate FuelPHP docs! [RELOADED]
Let’s translate FuelPHP docs! [RELOADED]Let’s translate FuelPHP docs! [RELOADED]
Let’s translate FuelPHP docs! [RELOADED]Sho A
 
ffi for rubyists
ffi for rubyistsffi for rubyists
ffi for rubyistsnanki
 
PHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようPHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようDQNEO
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.ContextAkira Takahashi
 
React+TypeScriptもいいぞ
React+TypeScriptもいいぞReact+TypeScriptもいいぞ
React+TypeScriptもいいぞMitsuru Ogawa
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presenKouhei Maeda
 
Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話Masakazu Muraoka
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話bleis tift
 
EC-CUBEプラグイン講義
EC-CUBEプラグイン講義EC-CUBEプラグイン講義
EC-CUBEプラグイン講義ria1201
 

Similar to GoらしいAPIを求める旅路 (Go Conference 2018 Spring) (20)

C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
 
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JP
 
明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理
 
Improvement future api
Improvement future apiImprovement future api
Improvement future api
 
AOSPをミラーしてみた
AOSPをミラーしてみたAOSPをミラーしてみた
AOSPをミラーしてみた
 
基礎からC言語 part1
基礎からC言語 part1基礎からC言語 part1
基礎からC言語 part1
 
Gopenflow demo v1
Gopenflow demo v1Gopenflow demo v1
Gopenflow demo v1
 
FuelPHPをさわってみて
FuelPHPをさわってみてFuelPHPをさわってみて
FuelPHPをさわってみて
 
第2回デザインパターン資料
第2回デザインパターン資料第2回デザインパターン資料
第2回デザインパターン資料
 
Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2
Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2
Optuna Dashboardの紹介と設計解説 - 2022/12/10 Optuna Meetup #2
 
Let’s translate FuelPHP docs! [RELOADED]
Let’s translate FuelPHP docs! [RELOADED]Let’s translate FuelPHP docs! [RELOADED]
Let’s translate FuelPHP docs! [RELOADED]
 
ffi for rubyists
ffi for rubyistsffi for rubyists
ffi for rubyists
 
PHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようPHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみよう
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
 
Deep Dive C# 6.0
Deep Dive C# 6.0Deep Dive C# 6.0
Deep Dive C# 6.0
 
React+TypeScriptもいいぞ
React+TypeScriptもいいぞReact+TypeScriptもいいぞ
React+TypeScriptもいいぞ
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presen
 
Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
 
EC-CUBEプラグイン講義
EC-CUBEプラグイン講義EC-CUBEプラグイン講義
EC-CUBEプラグイン講義
 

More from lestrrat

Future of Tech "Conferences"
Future of Tech "Conferences"Future of Tech "Conferences"
Future of Tech "Conferences"lestrrat
 
ONIの世界 - ONIcon 2019 Winter
ONIの世界 - ONIcon 2019 WinterONIの世界 - ONIcon 2019 Winter
ONIの世界 - ONIcon 2019 Winterlestrrat
 
Slicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPISlicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPIlestrrat
 
Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由lestrrat
 
Rejectcon 2018
Rejectcon 2018Rejectcon 2018
Rejectcon 2018lestrrat
 
Builderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinnerBuilderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinnerlestrrat
 
Google container builderと友だちになるまで
Google container builderと友だちになるまでGoogle container builderと友だちになるまで
Google container builderと友だちになるまでlestrrat
 
筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーション筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーションlestrrat
 
iosdc 2017
iosdc 2017iosdc 2017
iosdc 2017lestrrat
 
シュラスコの食べ方 超入門
シュラスコの食べ方 超入門シュラスコの食べ方 超入門
シュラスコの食べ方 超入門lestrrat
 
OSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃないOSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃないlestrrat
 
Coding in the context era
Coding in the context eraCoding in the context era
Coding in the context eralestrrat
 
Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)lestrrat
 
Opening: builderscon tokyo 2016
Opening: builderscon tokyo 2016Opening: builderscon tokyo 2016
Opening: builderscon tokyo 2016lestrrat
 
Kubernetes in 20 minutes - HDE Monthly Technical Session 24
Kubernetes in 20 minutes - HDE Monthly Technical Session 24Kubernetes in 20 minutes - HDE Monthly Technical Session 24
Kubernetes in 20 minutes - HDE Monthly Technical Session 24lestrrat
 
小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016lestrrat
 
いまさら聞けないselectあれこれ
いまさら聞けないselectあれこれいまさら聞けないselectあれこれ
いまさら聞けないselectあれこれlestrrat
 
Don't Use Reflect - Go 1.7 release party 2016
Don't Use Reflect - Go 1.7 release party 2016Don't Use Reflect - Go 1.7 release party 2016
Don't Use Reflect - Go 1.7 release party 2016lestrrat
 
How To Think In Go
How To Think In GoHow To Think In Go
How To Think In Golestrrat
 
On internationalcommunityrelations
On internationalcommunityrelationsOn internationalcommunityrelations
On internationalcommunityrelationslestrrat
 

More from lestrrat (20)

Future of Tech "Conferences"
Future of Tech "Conferences"Future of Tech "Conferences"
Future of Tech "Conferences"
 
ONIの世界 - ONIcon 2019 Winter
ONIの世界 - ONIcon 2019 WinterONIの世界 - ONIcon 2019 Winter
ONIの世界 - ONIcon 2019 Winter
 
Slicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPISlicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPI
 
Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由
 
Rejectcon 2018
Rejectcon 2018Rejectcon 2018
Rejectcon 2018
 
Builderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinnerBuilderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinner
 
Google container builderと友だちになるまで
Google container builderと友だちになるまでGoogle container builderと友だちになるまで
Google container builderと友だちになるまで
 
筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーション筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーション
 
iosdc 2017
iosdc 2017iosdc 2017
iosdc 2017
 
シュラスコの食べ方 超入門
シュラスコの食べ方 超入門シュラスコの食べ方 超入門
シュラスコの食べ方 超入門
 
OSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃないOSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃない
 
Coding in the context era
Coding in the context eraCoding in the context era
Coding in the context era
 
Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)
 
Opening: builderscon tokyo 2016
Opening: builderscon tokyo 2016Opening: builderscon tokyo 2016
Opening: builderscon tokyo 2016
 
Kubernetes in 20 minutes - HDE Monthly Technical Session 24
Kubernetes in 20 minutes - HDE Monthly Technical Session 24Kubernetes in 20 minutes - HDE Monthly Technical Session 24
Kubernetes in 20 minutes - HDE Monthly Technical Session 24
 
小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016
 
いまさら聞けないselectあれこれ
いまさら聞けないselectあれこれいまさら聞けないselectあれこれ
いまさら聞けないselectあれこれ
 
Don't Use Reflect - Go 1.7 release party 2016
Don't Use Reflect - Go 1.7 release party 2016Don't Use Reflect - Go 1.7 release party 2016
Don't Use Reflect - Go 1.7 release party 2016
 
How To Think In Go
How To Think In GoHow To Think In Go
How To Think In Go
 
On internationalcommunityrelations
On internationalcommunityrelationsOn internationalcommunityrelations
On internationalcommunityrelations
 

GoらしいAPIを求める旅路 (Go Conference 2018 Spring)