github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2012/chat.slide (about) 1 Go: code that grows with grace 2 3 Andrew Gerrand 4 Google Sydney 5 http://andrewgerrand.com 6 @enneff 7 http://golang.org 8 9 * Video 10 11 A video of this talk was recorded at Øredev in Malmö, Sweden in November 2012. 12 13 .link http://vimeo.com/53221560 Watch the talk on Vimeo 14 15 * Go 16 17 You may have heard of Go. 18 19 It's my favorite language. I think you'll like it, too. 20 21 * What is Go? 22 23 An open source (BSD licensed) project: 24 25 - Language specification, 26 - Small runtime (garbage collector, scheduler, etc), 27 - Two compilers (`gc` and `gccgo`), 28 - 'Batteries included' standard library, 29 - Tools (build, fetch, test, document, profile, format), 30 - Documentation. 31 32 As of September 2012 we have more than 300 contributors. 33 34 * Go is about composition 35 36 Go is Object Oriented, but not in the usual way. 37 38 - no classes (methods may be declared on any type) 39 - no subtype inheritance 40 - interfaces are satisfied implicitly (structural typing) 41 42 The result: simple pieces connected by small interfaces. 43 44 * Go is about concurrency 45 46 Go provides CSP-like concurrency primitives. 47 48 - lightweight threads (goroutines) 49 - typed thread-safe communication and synchronization (channels) 50 51 The result: comprehensible concurrent code. 52 53 * Go is about gophers 54 55 .image chat/gophers.jpg 56 57 * Core values 58 59 Go is about composition, concurrency, and gophers. 60 61 Keep that in mind. 62 63 * Hello, go 64 65 .play chat/support/hello.go 66 67 * Hello, net 68 69 .play chat/support/hello-net.go 70 71 * Interfaces 72 73 Hey neato! We just used `Fprintln` to write to a net connection. 74 75 That's because a `Fprintln` writes to an `io.Writer`, and `net.Conn` is an `io.Writer`. 76 77 .code chat/support/hello-net.go /Fprintln/ 78 .code chat/support/defs.go /Fprintln/ 79 .code chat/support/defs.go /type.Writer/,/^}/ 80 .code chat/support/defs.go /type.Conn/,/^}/ 81 82 * An echo server 83 84 .play chat/support/echo-no-concurrency.go 85 86 * A closer look at io.Copy 87 88 .code chat/support/echo-no-concurrency.go /Copy/ 89 .code chat/support/defs.go /Copy/,/func/ 90 .code chat/support/defs.go /type.Conn/,/^}/ 91 .code chat/support/defs.go /type.Writer/,/^}/ 92 .code chat/support/defs.go /type.Reader/,/^}/ 93 94 * Goroutines 95 96 Goroutines are lightweight threads that are managed by the Go runtime. To run a function in a new goroutine, just put `"go"` before the function call. 97 98 .play chat/support/goroutines.go 99 100 * A concurrent echo server 101 102 .play chat/support/echo.go 103 104 * "Chat roulette" 105 106 In this talk we'll look at a simple program, based on the popular "chat roulette" site. 107 108 In short: 109 110 - a user connects, 111 - another user connects, 112 - everything one user types is sent to the other. 113 114 * Design 115 116 The chat program is similar to the echo program. With echo, we copy a connection's incoming data back to the same connection. 117 118 For chat, we must copy the incoming data from one user's connection to another's. 119 120 Copying the data is easy. As in real life, the hard part is matching one partner with another. 121 122 * Design diagram 123 124 .image chat/diagrams.png 125 126 * Channels 127 128 Goroutines communicate via channels. A channel is a typed conduit that may be synchronous (unbuffered) or asynchronous (buffered). 129 130 .play chat/support/chan.go 131 132 * Select 133 134 A select statement is like a switch, but it selects over channel operations (and chooses exactly one of them). 135 136 .play chat/support/select.go 137 138 * Modifying echo to create chat 139 140 In the accept loop, we replace the call to `io.Copy`: 141 142 .code chat/support/echo.go /for {/,/\n }/ 143 144 with a call to a new function, `match`: 145 146 .code chat/tcp-simple/chat.go /for {/,/\n }/ 147 148 * The matcher 149 150 The `match` function simultaneously tries to send and receive a connection on a channel. 151 152 - If the send succeeds, the connection has been handed off to another goroutine, so the function exits and the goroutine shuts down. 153 - If the receive succeeds, a connection has been received from another goroutine. The current goroutine then has two connections, so it starts a chat session between them. 154 155 .code chat/tcp-simple/chat.go /var.partner/,/^}/ 156 157 * The conversation 158 159 The chat function sends a greeting to each connection and then copies data from one to the other, and vice versa. 160 161 Notice that it launches another goroutine so that the copy operations may happen concurrently. 162 163 .code chat/tcp-simple/chat.go /func.chat/,/^}/ 164 165 * Demo 166 167 * Error handling 168 169 It's important to clean up when the conversation is over. To do this we send the error value from each `io.Copy` call to a channel, log any non-nil errors, and close both connections. 170 171 .code chat/tcp/chat.go /func.chat/,/^}/ 172 .code chat/tcp/chat.go /func.cp/,/^}/ 173 174 * Demo 175 176 * Taking it to the web 177 178 "Cute program," you say, "But who wants to chat over a raw TCP connection?" 179 180 Good point. Let's modernize it by turning it a web application. 181 182 Instead of TCP sockets, we'll use websockets. 183 184 We'll serve the user interface with Go's standard `net/http` package, and websocket support is provided by the `websocket` package from the `go.net` sub-repository, 185 186 * Hello, web 187 188 .play chat/support/hello-web.go 189 190 * Hello, WebSocket 191 192 .code chat/support/websocket.js 193 .play chat/support/websocket.go 194 195 * Using the http and websocket packages 196 197 .code chat/http/chat.go /package/,/^}/ 198 199 * Serving the HTML and JavaScript 200 201 .code chat/http/html.go /import/ 202 .code chat/http/html.go /func/,/<script>/ 203 .code chat/http/html.go /websocket.=/,/onClose/ 204 .code chat/http/html.go /<\/html>/,$ 205 206 * Adding a socket type 207 208 We can't just use a `websocket.Conn` instead of the `net.Conn`, because a `websocket.Conn` is held open by its handler function. Here we use a channel to keep the handler running until the socket's `Close` method is called. 209 210 .code chat/http-noembed/chat.go /type.socket/,/END/ 211 212 * Struct embedding 213 214 Go supports a kind of "mix-in" functionality with a feature known as "struct embedding". The embedding struct delegates calls to the embedded type's methods. 215 216 .play chat/support/embed.go /type/,$ 217 218 * Embedding the websocket connection 219 220 By embedding the `*websocket.Conn` as an `io.ReadWriter`, we can drop the explicit `socket` `Read` and `Write` methods. 221 222 .code chat/http/chat.go /type.socket/,/END/ 223 224 * Demo 225 226 * Relieving loneliness 227 228 What if you connect, but there's noone there? 229 230 Wouldn't it be nice if we could synthesize a chat partner? 231 232 Let's do it. 233 234 * Generating text with markov chains 235 236 .code chat/support/markov.txt 237 238 * Generating text with markov chains 239 240 Fortunately, the Go docs include a markov chain implementation: 241 242 .link http://golang.org/doc/codewalk/markov 243 244 We'll use a version that has been modified to be safe for concurrent use. 245 246 .code chat/markov/markov.go /Chain/,/{/ 247 .code chat/markov/markov.go /Write/,/{/ 248 .code chat/markov/markov.go /Generate/,/{/ 249 250 * Feeding the chain 251 252 We will use all text that enters the system to build the markov chains. 253 To do this we split the socket's `ReadWriter` into a `Reader` and a `Writer`, 254 and feed all incoming data to the `Chain` instance. 255 256 .code chat/markov/chat.go /type.socket/,/^}/ 257 .code chat/markov/chat.go /var.chain/,/^}/ 258 259 * The markov bot 260 261 .code chat/markov/chat.go /\/\/.Bot/,/^}/ 262 .code chat/markov/chat.go /type.bot/,/^}/ 263 .code chat/markov/chat.go /func.+bot.+Write/,/^}/ 264 .code chat/markov/chat.go /func.+bot.+speak/,/^}/ 265 266 * Integrating the markov bot 267 268 The bot should jump in if a real partner doesn't join. 269 To do this, we add a case to the select that triggers after 5 seconds, starting a chat between the user's socket and a bot. 270 271 .code chat/markov/chat.go /func.match/,/^}/ 272 273 The `chat` function remains untouched. 274 275 * Demo 276 277 * One more thing 278 279 * TCP and HTTP at the same time 280 281 .code chat/both/chat.go /func main/,/^}/ 282 .code chat/both/chat.go /func netListen/,/^}/ 283 284 * Demo 285 286 * Discussion 287 288 * Further reading 289 290 All about Go: 291 292 .link http://golang.org 293 294 The slides for this talk: 295 296 .link http://talks.golang.org/2012/chat.slide 297 298 "Go Concurrency Patterns" by Rob Pike: 299 300 .link http://golang.org/s/concurrency-patterns