Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
go doSomeThing()
Search
Jérémy Courtial
February 24, 2016
Programming
63
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
go doSomeThing()
Jérémy Courtial
February 24, 2016
More Decks by Jérémy Courtial
See All by Jérémy Courtial
sudo give the cloud
mrartichaut
0
36
An introduction to AppSec?
mrartichaut
0
57
Secure by design: introduction to threat modeling
mrartichaut
0
67
Taming secrets with Vault
mrartichaut
0
110
Lead Tech: Empowering the team
mrartichaut
0
56
Web Platform Security
mrartichaut
0
62
Practical Cryptography : Data Encryption
mrartichaut
0
76
Practical Cryptography : Password Hashing
mrartichaut
1
84
HTTP/2 : One connection to rule them all
mrartichaut
1
77
Other Decks in Programming
See All in Programming
golang-bob.pdf
iwatsukayura
0
130
Agents on Rails - Rails at Scale 2026
irinanazarova
0
540
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.4k
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
210
Verilogで学ぶCPU自作入門
uyuki234
8
4.1k
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
8
6k
Kotlinの15年とServer-Side Kotlin
n_takehata
1
140
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
250
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Rails World 2026, Austin, Texas
marcoroth
0
210
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
1
190
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
390
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.1k
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Evolving SEO for Evolving Search Engines
ryanjones
0
320
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
570
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Leo the Paperboy
mayatellez
10
2.4k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
730
A Tale of Four Properties
chriscoyier
163
24k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Product Roadmaps are Hard
iamctodd
55
13k
Transcript
go doSomething() author := "Jérémy Courtial"
// Pragmatic & productive // language for efficient // softwares
type GoLang struct { … }
go.creationYear = "2007" go.authors = []Author{ "Robert Griesemer", "Rob Pike",
"Ken Thompson"}
go.users = []Company{ "Google", "Docker" "SoundCloud", "Dropbox", "Facebook", "CoreOS", "Cloudflare",
… }
go := Language{ memManagement: gc, packaging: fatBinary, crossPlatform: true
…
… paradigm: imperative, typeSystem: static-inferred, licence: openSource }
import "fmt"
import "fmt" func main() { }
import "fmt" func main() { msg := "Hello, World" }
import "fmt" func main() { msg := "Hello, World" fmt.Println(msg)
}
// Go has interface type Human interface { SayHello() }
// Struct is a class equiv. type HomoSapiens struct {
Name string Age int }
func (hs HomoSapiens) SayHello { }
func (hs HomoSapiens) SayHello { fmt.Println("Hi, i'm", hs.Name) }
// Now HomoSapiens implements Human func (hs HomoSapiens) SayHello {
fmt.Println("Hi, i'm", hs.Name) }
/* "Favor 'object composition' over 'class inheritance'." Design Patterns, GoF,
1995 */
type Robot interface { DestroyHumanity() }
type Cyborg struct { Human Robot gadgets []Gadget }
t800 := Cyborg { }
t800 := Cyborg { human: HumanImpl{}, }
t800 := Cyborg { human: HumanImpl{}, robot: RobotImpl{}, }
t800 := Cyborg { human: HumanImpl{}, robot: RobotImpl{}, gadgets: lethalGadgets,
}
t800.SayHello() t800.DestroyHumanity()
// golang.org/doc/effective_go.html
go.missings = []Feature{ }
go.missings = []Feature{ "Generics", }
go.missings = []Feature{ "Generics", "Pointer Arithmetic", }
go.missings = []Feature{ "Generics", "Pointer Arithmetic", "try/catch", }
go.missings = []Feature{ "Generics", "Pointer Arithmetic", "try/catch", "Implicit Conversions"}
go.tools = []Tool{ "go build", "go fmt", "go get", "go
vet", … }
go.stdLib = []Package{ "net/http", "crypto/aes", "encoding/json", "sort", "bytes", "compress/gzip", "image/png",
"net/html", … }
func NewCipher(key []byte) (cipher.Block, error) type Block interface {
BlockSize() int Encrypt(dst, src []byte) Decrypt(dst, src []byte) }
func main() { http.HandleFunc("/hi", func(w http.ResponseWriter, r *http.Request ) {
msg := map[string]string {"msg": "Hello, World!"} j, _ := json.Marshal(msg) w.Write(j) }) http.ListenAndServe(":8080", nil) }
go.concurrency = LigthAndFastImpl{}
go doSomthingForAWhile()
/* Don't communicate by sharing, share by communicating. */
// Instanciates a channel of strings c := make(chan string)
go work(c)
func work(c chan string) { }
func work(c chan string) { for { } }
func work(c chan string) { for { msg := <-
c } }
func work(c chan string) { for { msg := <-
c fmt.Println(msg) } }
c <- "Hello World!" time.Sleep(5) c <- "Have a nice
day!" time.Sleep(5) c <- "Bye bye!"
func work(quit, c chan int) { }
func work(quit, c chan int) { select { } }
func work(quit, c chan int) { select { case n
:= <- c : } }
func work(quit, c chan int) { select { case n
:= <- c : process(n) } }
func work(quit, c chan int) { select { case n
:= <- c : process(n) case <- quit : } }
func work(quit, c chan int) { select { case n
:= <- c : process(n) case <- quit : return } }
// Why Go's concurrency is special ?
define("C10k problem")
// Most evident tool type Thread struct { … }
/* Be naive : One thread per connection */
for { }
for { conn := tcp.accept() }
for { conn := tcp.accept() newThread() }
for { conn := tcp.accept() newThread().run( func() { }) }
for { conn := tcp.accept() newThread().run( func() { handleConnection(conn) })
}
#BEGIN JAVA #END JAVA // Quick & dirty POC
#BEGIN JAVA #END JAVA while (true) { } // Quick
& dirty POC
#BEGIN JAVA #END JAVA while (true) { new Thread(() ->
{ }); } // Quick & dirty POC
#BEGIN JAVA #END JAVA while (true) { new Thread(() ->
{ sleep(Long.MAX_VALUE); }); } // Quick & dirty POC
#BEGIN JAVA #END JAVA while (true) { new Thread(() ->
{ sleep(Long.MAX_VALUE); }); } // What will happen ?
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native
thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:714) at Test.main(Test.java:19) $ javac Test.java && java Test
/* - Each thread has is own stack - Stack's
size is hard to predict => alloc ~1 Mo per thread */
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | . | | . | | . | | . | | . | | . | | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | Guard Page | | — — — — — — — - - - - | | . | | . | | . | | . | | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | Guard Page | | — — — — — — — - - - - | | Thread Stack 2 | |- - - - - - - - - - - -| | . | | . | | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | Guard Page | | — — — — — — — - - - - | | Thread Stack 2 | |- - - - - - - - - - - -| | Guard Page | |- - - - - - - - - - - -| | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
// Let's try something else … pool := NewThreadPool(n)
pool.submit(work)
work := func() { // Blocks until done … readFromNetwork()
}
if pool.hasAvailableThread == false { gameOver() }
// We need different tools IO.asynchronous = true
/* The Hollywood Principle : "Don't call us, we'll call
you" */
b := readFromNetwork() //Block here /* With synchronous I/O */
readFromNetwork(func(b []byte) { //Call when data are available }) /*
With asynchronous I/O */
// Let's try something else … type EventDriven struct {
… }
// Event Driven // Always use async I/O // Considers
I/O as events producers // Events are gathered by a loop
const ( NewConnectionEvent = 1 DataAvailableEvent = 2 DataSentEvent =
3 … )
type Event struct { type EventType callback func() result []byte
}
loop := NewEventLoop() thread.run(loop)
func (l loop) run() { }
func (l loop) run() { for { } }
func (l loop) run() { for { events := os.GatherEvents()
} }
func (l loop) run() { for { events := os.GatherEvents()
l.dispatch(events) } }
func (l loop) dispatch(e []Event) { }
func (l loop) dispatch(e []Event) { for event := range
e { } }
func (l loop) dispatch(e []Event) { for event := range
e { event.callback(e.result) } }
// Drawbacks
// Callbacks hells
s.onNewConnection(func(…){ … }).onDataAvailable(func(…){ … }) s.sendData(data, func(…){ … })
// Singled threaded // Bad for vertical scaling thread.run(loop)
// We need different tools
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | | | | | | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | Applications | | | | | | | | | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | Applications | | | | Daemons | | | | | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | Applications | | | | Daemons | | | | Librairies | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | NewOSThread() | | | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| // Kernel threads
|- — — — — — — - - -
- -| | | | | | NewOSThread() | | | | | | |- - - - - | - - - - - -| | ∨ | | | | kernel_thread(…) | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| // Kernel threads
|- — — — — — — - - -
- -| | | | User Thread 1 | | | | | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | | | User Thread 1 | | User Thread 2 | | | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | | | User Thread 1 | | User Thread 2 | | User Thread 3 | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | — — — — — — — — | | | User Thread 1 | | | | User Thread 2 | | | | User Thread 3 | | | - - - - - - - - | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | — — — — — — — — | | | User Thread 1 | | | | User Thread 2 | | | | User Thread 3 | | | - - - | - - - - | |- - - - - | - - - - - -| | ∨ | | | | kernel_thread(…) | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads N:M */
// User Threads // Cheaper than kernel threads // Backed
by one or more K threads // App is responsible for scheduling
goroutines == User threads
// Goroutines are // Cheap in memory : 2 Ko
only // Cheap to create/destroy // Cheap to switch
for { }
for { conn := tcp.accept() }
for { conn := tcp.accept() go handleConnection(conn) }
func handleConnection(c net.Conn){ }
func handleConnection(c net.Conn){ data := c.Read(4096) }
func handleConnection(c net.Conn){ data := c.Read(4096) response := process(data) }
func handleConnection(c net.Conn){ data := c.Read(4096) response := process(data) c.Write(response)
}
data := c.Read(4096)
data := c.Read(4096) // Blocks the goroutine until // data
are available
data := c.Read(4096) // But don't block the thread //
and other goroutines
// Goroutines scheduling // Scheduling is cooperative // Blocking IOs
used as switch point // When a gorountine blocks another // is wake up
/* Now you can be naive : One thread per
connection */ goroutine
/* The gopher way : Focus on what you want
to do */
// Let's go ?
// October 10, 2016 · PARIS
/* Bibliography golang.org tour.golang.org talks.golang.org */
/* Bibliography The Go scheduler How Goroutines work Performance Without
The Event Loop */
// Thanks // Questions ?