SlideShare a Scribd company logo
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
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
APIデザインをする時はその言
語の自然なフローを許す形を
考えるのがお勧め
(なお、コードをよく読むと、
cenkalti/backoffも実装はほぼ同じ仕
組みになっているが、公開しているイ
ンターフェースがまったく違う)
おまけ
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
「Google APIから学ぶ自動生成」
※ Goの連載記事です
※ GoのためのAPIデザインの話です
End
Ad

More Related Content

What's hot (20)

ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門
増田 亨
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
Kohei Tokunaga
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
yoku0825
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
Takuto Wada
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMP
Yusuke Kagata
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
Kumazaki Hiroki
 
分散システムについて語らせてくれ
分散システムについて語らせてくれ分散システムについて語らせてくれ
分散システムについて語らせてくれ
Kumazaki Hiroki
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
 
PostgreSQLアンチパターン
PostgreSQLアンチパターンPostgreSQLアンチパターン
PostgreSQLアンチパターン
Soudai Sone
 
Gitの便利ワザ
Gitの便利ワザGitの便利ワザ
Gitの便利ワザ
ktateish
 
マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜
Yoshiki Nakagawa
 
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3 データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
Hiroshi Ito
 
なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?
ichirin2501
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
shigeki_ohtsu
 
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?
Yoshitaka Kawashima
 
トランザクションの設計と進化
トランザクションの設計と進化トランザクションの設計と進化
トランザクションの設計と進化
Kumazaki Hiroki
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
Yoshitaka Kawashima
 
イミュータブルデータモデルの極意
イミュータブルデータモデルの極意イミュータブルデータモデルの極意
イミュータブルデータモデルの極意
Yoshitaka Kawashima
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
Yuji Otani
 
PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)
PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)
PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)
Koichiro Matsuoka
 
ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門
増田 亨
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
Kohei Tokunaga
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
yoku0825
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
Takuto Wada
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMP
Yusuke Kagata
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
Kumazaki Hiroki
 
分散システムについて語らせてくれ
分散システムについて語らせてくれ分散システムについて語らせてくれ
分散システムについて語らせてくれ
Kumazaki Hiroki
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
 
PostgreSQLアンチパターン
PostgreSQLアンチパターンPostgreSQLアンチパターン
PostgreSQLアンチパターン
Soudai Sone
 
Gitの便利ワザ
Gitの便利ワザGitの便利ワザ
Gitの便利ワザ
ktateish
 
マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜
Yoshiki Nakagawa
 
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3 データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
Hiroshi Ito
 
なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?
ichirin2501
 
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?
Yoshitaka Kawashima
 
トランザクションの設計と進化
トランザクションの設計と進化トランザクションの設計と進化
トランザクションの設計と進化
Kumazaki Hiroki
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
Yoshitaka Kawashima
 
イミュータブルデータモデルの極意
イミュータブルデータモデルの極意イミュータブルデータモデルの極意
イミュータブルデータモデルの極意
Yoshitaka Kawashima
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
Yuji Otani
 
PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)
PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)
PostgreSQLの行レベルセキュリティと SpringAOPでマルチテナントの ユーザー間情報漏洩を防止する (JJUG CCC 2021 Spring)
Koichiro Matsuoka
 

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

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 JP
Akira Takahashi
 
明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理
Yuto Matsukubo
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
 
AOSPをミラーしてみた
AOSPをミラーしてみたAOSPをミラーしてみた
AOSPをミラーしてみた
kinneko
 
基礎からC言語 part1
基礎からC言語 part1基礎からC言語 part1
基礎からC言語 part1
Hiroyuki Ito
 
Gopenflow demo v1
Gopenflow demo v1Gopenflow demo v1
Gopenflow demo v1
Hiroaki Kawai
 
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 #2
Preferred 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 rubyists
nanki
 
PHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようPHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみよう
DQNEO
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
Akira Takahashi
 
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もいいぞ
Mitsuru Ogawa
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presen
Kouhei Maeda
 
Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話
Masakazu Muraoka
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
bleis tift
 
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 JP
Akira Takahashi
 
明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理明日から使える気になるGo言語による並行処理
明日から使える気になるGo言語による並行処理
Yuto Matsukubo
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
 
AOSPをミラーしてみた
AOSPをミラーしてみたAOSPをミラーしてみた
AOSPをミラーしてみた
kinneko
 
基礎からC言語 part1
基礎からC言語 part1基礎からC言語 part1
基礎からC言語 part1
Hiroyuki 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 #2
Preferred 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 rubyists
nanki
 
PHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみようPHPの戻り値型宣言でselfを使ってみよう
PHPの戻り値型宣言でselfを使ってみよう
DQNEO
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
Akira Takahashi
 
React+TypeScriptもいいぞ
React+TypeScriptもいいぞReact+TypeScriptもいいぞ
React+TypeScriptもいいぞ
Mitsuru Ogawa
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presen
Kouhei Maeda
 
Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話
Masakazu Muraoka
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
bleis tift
 
Ad

More from lestrrat (20)

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 Winter
lestrrat
 
Slicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPISlicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPI
lestrrat
 
Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由
lestrrat
 
Rejectcon 2018
Rejectcon 2018Rejectcon 2018
Rejectcon 2018
lestrrat
 
Builderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinnerBuilderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinner
lestrrat
 
Google container builderと友だちになるまで
Google container builderと友だちになるまでGoogle container builderと友だちになるまで
Google container builderと友だちになるまで
lestrrat
 
筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーション筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーション
lestrrat
 
iosdc 2017
iosdc 2017iosdc 2017
iosdc 2017
lestrrat
 
シュラスコの食べ方 超入門
シュラスコの食べ方 超入門シュラスコの食べ方 超入門
シュラスコの食べ方 超入門
lestrrat
 
OSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃないOSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃない
lestrrat
 
Coding in the context era
Coding in the context eraCoding in the context era
Coding in the context era
lestrrat
 
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 2016
lestrrat
 
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
lestrrat
 
小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016
lestrrat
 
いまさら聞けない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 2016
lestrrat
 
How To Think In Go
How To Think In GoHow To Think In Go
How To Think In Go
lestrrat
 
On internationalcommunityrelations
On internationalcommunityrelationsOn internationalcommunityrelations
On internationalcommunityrelations
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 Winter
lestrrat
 
Slicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPISlicing, Dicing, And Linting OpenAPI
Slicing, Dicing, And Linting OpenAPI
lestrrat
 
Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由Oxygen Not Includedをやるべき4つの理由
Oxygen Not Includedをやるべき4つの理由
lestrrat
 
Rejectcon 2018
Rejectcon 2018Rejectcon 2018
Rejectcon 2018
lestrrat
 
Builderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinnerBuilderscon tokyo 2018 speaker dinner
Builderscon tokyo 2018 speaker dinner
lestrrat
 
Google container builderと友だちになるまで
Google container builderと友だちになるまでGoogle container builderと友だちになるまで
Google container builderと友だちになるまで
lestrrat
 
筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーション筋肉によるGoコードジェネレーション
筋肉によるGoコードジェネレーション
lestrrat
 
iosdc 2017
iosdc 2017iosdc 2017
iosdc 2017
lestrrat
 
シュラスコの食べ方 超入門
シュラスコの食べ方 超入門シュラスコの食べ方 超入門
シュラスコの食べ方 超入門
lestrrat
 
OSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃないOSSの敵になるのもいいじゃない
OSSの敵になるのもいいじゃない
lestrrat
 
Coding in the context era
Coding in the context eraCoding in the context era
Coding in the context era
lestrrat
 
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 2016
lestrrat
 
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
lestrrat
 
小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016小規模でもGKE - DevFest Tokyo 2016
小規模でもGKE - DevFest Tokyo 2016
lestrrat
 
いまさら聞けない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 2016
lestrrat
 
How To Think In Go
How To Think In GoHow To Think In Go
How To Think In Go
lestrrat
 
On internationalcommunityrelations
On internationalcommunityrelationsOn internationalcommunityrelations
On internationalcommunityrelations
lestrrat
 
Ad

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