Text file
talks/2012/insidepresent.slide
1 Inside the "present" tool
2
3 Andrew Gerrand
4 Google
5 @enneff
6 adg@golang.org
7 https://go.dev
8
9
10 * The Playground API
11
12 The API used by the Playground (and the Tour) is a simple HTTP POST request
13 that returns a JSON-encoded response.
14
15 Request:
16
17 POST /compile HTTP/1.1
18 Host:play.golang.org
19 Content-Length:113
20 Content-Type:application/x-www-form-urlencoded; charset=UTF-8
21
22 body=package+main%0A%0Aimport+%22fmt%22%0A%0Afunc+main()+%7B%0A%09fmt.Println(%22Hello%2C+playground%22)%0A%7D%0A
23
24 Response body:
25
26 {"compile_errors":"","output":"Hello, playground\n"}
27
28
29 * Playground drawbacks
30
31 The compile service has no concept of time. (Necessary to limit resource use.)
32
33 The API reflects this; output is sent in one blob, not streamed.
34
35 Even when running locally, the API is bad for demonstrating code that uses time.
36
37 Rob needed to use time in his _Go_Concurrency_Patterns_ talk.
38
39
40 * Enter WebSockets
41
42 WebSockets are a bi-directional communication channel between a JavaScript program running in a web browser and a web server. They are part of HTML 5.
43
44 The `websocket` package in Go's `go.net` sub-repository provides a WebSocket client and server.
45
46 I thought I could use WebSockets to stream program output to a running
47 presentation.
48
49 And thus the `present` tool was born.
50
51
52 * Hello, WebSocket
53
54 .code insidepresent/websocket.js
55 .play insidepresent/websocket.go
56
57
58 * Messages
59
60 The client (browser) and server (present) communicate with JSON-encoded messages.
61
62 .code insidepresent/socket.go /Message is/,/^}/
63
64 Go's `encoding/json` format can convert these `Message` values to and from JSON.
65
66 Go:
67
68 Message{Id: "0", Kind: "run", Body: `package main; func main() { print("hello"); }`}
69
70 JSON:
71
72 {"Id":"0","Kind":"run","Body":"package main; func main() { print(\"hello\"); }"}
73
74
75 * On the wire
76
77 .play insidepresent/hello.go
78
79 .html insidepresent/wire.html
80
81
82 * Implementation
83
84 * socketHandler (1/3)
85
86 First, register the handler with the `net/http` package:
87
88 http.Handle("/socket", websocket.Handler(socketHandler))
89
90 Implementation:
91
92 .code insidepresent/socket.go /func socketHandler/,/errc/
93
94 * socketHandler (2/3)
95
96 .code insidepresent/socket.go /Decode messages/,/END/
97
98 * socketHandler (3/3)
99
100 .code insidepresent/socket-simple.go /Start and kill/,/^}/
101
102
103 * Process
104
105 .code insidepresent/socket.go /Process represents/,/^}/
106
107 * StartProcess
108
109 .code insidepresent/socket.go /StartProcess builds/,/^}/
110
111 * Process.start (1/2)
112
113 .code insidepresent/socket.go /start builds/,/END/
114
115 * Process.start (2/2)
116
117 .code insidepresent/socket.go /build x\.go/,/^}/
118
119 * Process.cmd
120
121 .code insidepresent/socket.go /cmd builds/,/^}/
122 .code insidepresent/socket.go /messageWriter is/,/END/
123
124 * Process.wait and Process.end
125
126 .code insidepresent/socket.go /wait waits/,/^}/
127 .code insidepresent/socket.go /end sends/,/^}/
128
129 * Process.Kill
130
131 .code insidepresent/socket.go /Kill stops/,/^}/
132
133
134 * One more thing
135
136 * Limiting output (1/2)
137
138 .code insidepresent/socket.go /switch m\.Kind/,/^ }/
139
140 * Limiting output (2/2)
141
142 .code insidepresent/socket.go /limiter returns/,/^}/
143
144
145
View as plain text