github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2015/go4cpp.slide (about) 1 Go for C++ developers 2 3 Francesc Campoy 4 Developer, Advocate, and Gopher at Google 5 @francesc 6 campoy@golang.org 7 8 #go4cpp 9 10 * Go for C++ developers 11 12 Agenda: 13 14 - let's talk about Go 15 16 - how do I do X in Go? 17 18 - concurrency, because it's awesome 19 20 - Q & A: but feel free to interrupt anytime 21 22 - We might not go through all the slides 23 24 * About me 25 26 *2011* Joined Google as a Software Engineer 27 28 - writing mostly in C++ and Python 29 - used to think _smart_code_ was better than boring code 30 31 *2012* Joined the Go team as a Developer Programs Engineer 32 33 *2014*to*today* Developer Advocate for the Google Cloud Platform 34 35 * Let's talk about Go 36 37 * Go is 38 39 Go is 40 41 - open source 42 43 - statically typed 44 45 - object oriented (if you ask me) 46 47 - compiled 48 49 - memory safe 50 51 - type safe 52 53 * Why Go? 54 55 Go was created for: 56 57 - scalability 58 59 - concurrency 60 61 - simplicity 62 63 * Who uses Go? 64 65 Google: 66 67 - YouTube 68 - dl.google.com 69 70 Others: 71 72 - Docker 73 - SoundCloud 74 - Canonical 75 - CloudFlare 76 - Mozilla 77 - ... 78 79 [[http://golang.org/wiki/GoUsers][golang.org/wiki/GoUsers]] 80 81 * Who uses Go? 82 83 .image go4cpp/trends.png _ 800 84 85 .caption Google Trends for [[http://www.google.com/trends/explore#q=golang][golang]] 86 87 * Some Go features 88 89 * Go types 90 91 - primitive types 92 93 int, uint, int8, uint8, ... 94 bool, string 95 float32, float64 96 complex64, complex128 97 98 - structs 99 100 struct { 101 Name string 102 Age int 103 } 104 105 - slices and arrays 106 107 []int, [3]string, []struct{ Name string } 108 109 - maps 110 111 map[string]int 112 113 * Kinds of types (continued) 114 115 - pointers 116 117 *int, *Person 118 119 - functions 120 121 func(int, int) int 122 123 - channels 124 125 chan bool 126 127 - interfaces 128 129 interface { 130 Start() 131 Stop() 132 } 133 134 * Type declarations 135 136 type [name] [specification] 137 138 `Person` is a `struct` type. 139 140 type Person struct { 141 name string 142 age int 143 } 144 145 `Celsius` is a `float64` type. 146 147 type Celsius float64 148 149 * Function declarations 150 151 func [name] ([params]) [return value] 152 func [name] ([params]) ([return values]) 153 154 A sum function: 155 156 func sum(a int, b int) int { 157 return a + b 158 } 159 160 A function with multiple return values: 161 162 func divMod(a, b int) (int, int) { 163 return a / b, a % b 164 } 165 166 Made clearer by naming the return values: 167 168 func divMod(den, div int) (quo, rem int) { 169 return den / div, den % div 170 } 171 172 * Method declarations 173 174 func ([receiver]) [name] ([params]) ([return values]) 175 176 A method on a struct: 177 178 func (p Person) IsMinor() bool { 179 return p.age < 18 180 } 181 182 But also a method on a `float64`: 183 184 func (c Celsius) Freezing() bool { 185 return c <= 0 186 } 187 188 _Constraint:_ Methods can be defined *only* on types declared in the same package. 189 190 // This won't compile 191 func (s string) Length() int { return len(s) } 192 193 * Declaring variables 194 195 Normal declaration: 196 197 var text string = "hello" 198 199 You can omit types: 200 201 var text = "hello" 202 203 And inside of functions: 204 205 text := "hello" 206 207 Other types 208 209 a := 0 // int 210 b := true // boolean 211 f := 1.0 // float64 212 p := Person{"Francesc", "Campoy"} // Person 213 214 * No implicit numeric conversion 215 216 Given types: 217 218 type Celsius float64 219 220 type Fahrenheit float64 221 222 And the variables: 223 224 var freezing Fahrenheit = 32 225 var boiling Celsius = 100 226 227 This code won't compile: 228 229 sauna := (freezing + boiling) / 2 230 231 There's no implicit numeric conversion in Go. 232 233 * Pointers and memory allocation 234 235 * Pointers 236 237 Go has pointers: 238 239 var p *int 240 p = new(int) 241 242 But no pointer arithmetics: 243 244 var p *int = &a[0] 245 var q = p+2 // invalid 246 247 There's `new` but there's no `delete`. 248 249 Memory is garbaged collected after it's no longer accessible. 250 251 * Memory allocation 252 253 The compiler decides where to allocate based on escape analysis. 254 255 Using `new` doesn't imply using the heap: 256 257 `stack.go`: 258 259 func get() int { 260 n := new(int) 261 return *n 262 } 263 264 And not all values in the heap are created with `new`: 265 266 `heap.go`: 267 268 func get() *int { 269 n := 4 270 return &n 271 } 272 273 * Choosing what allocation you want 274 275 You can *not* decide where a value is allocated. 276 277 But you can see what kind of allocation is used: 278 279 $ go tool 6g -m stack.go 280 281 stack.go:3: can inline get 282 stack.go:4: get new(int) does not escape 283 284 Compare to: 285 286 $ go tool 6g -m heap.go 287 288 heap.go:3: can inline get 289 heap.go:4: moved to heap: n 290 heap.go:5: &n escapes to heap 291 292 * RAII 293 294 _Resource_Acquisition_Is_Initialization_ 295 296 Provides: 297 298 - encapsulation of acquisition and disposition of resources 299 300 - exception safe 301 302 An example: 303 304 void write_to_file (const std::string & message) { 305 // mutex to protect file access 306 static std::mutex mutex; 307 308 // lock mutex before accessing file 309 // at the end of the scope unlock mutex 310 std::lock_guard<std::mutex> lock(mutex); 311 312 // mutual exclusion access section 313 ... 314 } 315 316 * RAII in Go: defer 317 318 The `defer` statement: 319 320 - schedules a function call at the end of the current function 321 322 - stacks all deferred calls - last in first out 323 324 var m sync.Mutex 325 326 func writeToFile(msg string) error { 327 m.Lock() 328 defer m.Unlock() 329 330 // mutual exclusion access section 331 } 332 333 * Garbage collection 334 335 Go is a garbage collected language 336 337 But it's easy to limit heap allocations 338 339 - many values are allocated on the stack 340 341 - object pools: [[sync.Pool][http://golang.org/pkg/sync/#Pool]] 342 343 - contiguous area of memory 344 345 .play go4cpp/sizes.go /type/, 346 347 * More about garbage collection 348 349 Trusted in production. 350 351 Brad Fitzpatrick's talk on migrating dl.google.com from C++ to Go: 352 353 - [[https://talks.golang.org/2013/oscon-dl.slide#1][dl.google.com: Powered by Go]] 354 355 Current state and road plan: 356 357 - [[http://golang.org/s/go14gc][golang.org/s/go14gc]] 358 359 * Inheritance vs Composition 360 361 * Inheritance vs Composition 362 363 - Inheritance breaks encapsulation 364 365 - Composition causes boilerplate to proxy all methods 366 367 Example: 368 369 type Engine struct{} 370 371 func (e Engine) Start() { ... } 372 func (e Engine) Stop() { ... } 373 374 We want `Car` to be able to `Start` and `Stop` too. 375 376 More detail in my talk [[http://talks.golang.org/2014/go4java.slide#32][Go for Javaneros]] 377 378 * Struct embedding 379 380 Composition + Proxy of selectors 381 382 .play go4cpp/embedding.go /type/, 383 384 * Struct embedding and the diamond problem 385 386 What if two embedded fields have the same type? 387 388 .play go4cpp/diamond.go /type/, 389 390 * Struct embedding 391 392 It looks like inheritance but _it_is_not_inheritance_. 393 394 It is composition. 395 396 Used to share implementations between different types. 397 398 What if want to share behavior instead? 399 400 * Interfaces 401 402 * Interfaces 403 404 An interface is a set of methods. 405 406 In Java (C++ doesn't have interfaces) 407 408 interface Switch { 409 void open(); 410 void close(); 411 } 412 413 In Go: 414 415 type OpenCloser interface { 416 Open() 417 Close() 418 } 419 420 * It's all about satisfaction 421 422 Java interfaces are satisfied *explicitly*. 423 424 C++ abstract classes need to be extended *explicitly* 425 426 Go interfaces are satisfied *implicitly*. 427 428 .image //upload.wikimedia.org/wikipedia/commons/thumb/2/29/Rolling_Stones_09.jpg/512px-Rolling_Stones_09.jpg _ 512 429 430 .caption Picture by Gorupdebesanez [[http://creativecommons.org/licenses/by-sa/3.0][CC-BY-SA-3.0]], via [[http://commons.wikimedia.org/wiki/File%3ARolling_Stones_09.jpg][Wikimedia Commons]] 431 432 * Go: implicit satisfaction 433 434 _If_a_type_defines_all_the_methods_of_an_interface,_the_type_satisfies_that_interface._ 435 436 Benefits: 437 438 - fewer dependencies 439 - no type hierarchy 440 - organic composition 441 442 * Structural subtyping 443 444 Better than duck typing. Verified at compile time. 445 446 .image go4cpp/duck.jpg 500 500 447 448 * FuncDraw: an example on interfaces 449 450 .image go4cpp/funcdraw.png 500 700 451 452 * FuncDraw: package parser 453 454 Package `parse` provides a parser of strings into functions. 455 456 func Parse(text string) (*Func, error) { ... } 457 458 `Func` is a struct type, with an `Eval` method. 459 460 type Func struct { ... } 461 462 func (p *Func) Eval(x float64) float64 { ... } 463 464 * FuncDraw: package draw 465 466 Package draw generates images given a function. 467 468 func Draw(f *parser.Func) image.Image { 469 for x := start; x < end; x += inc { 470 y := f.Eval(x) 471 ... 472 } 473 } 474 475 `draw` depends on `parser`, which makes testing hard. 476 477 * Breaking dependencies 478 479 Let's use an interface instead 480 481 type Evaluable interface { 482 Eval(float64) float64 483 } 484 485 func Draw(f Evaluable) image.Image image.Image { 486 for x := start; x < end; x += inc { 487 y := f.Eval(x) 488 ... 489 } 490 } 491 492 * Advanced interfaces and composition 493 494 * Struct embedding of interfaces 495 496 Embedding an interface: 497 498 - more types can be used 499 - limits what is added to the embedding type 500 501 Given: 502 503 type Person struct { 504 First string 505 Last string 506 Age int 507 } 508 509 `Employee` exposes the `Age` of `Person` 510 511 type Employee struct { 512 Person 513 } 514 515 e := Employee{Person{"John", "Doe", 49}} 516 517 * Choosing what to proxy 518 519 But we could hide it by choosing an interface: 520 521 type Employee struct { 522 Namer 523 } 524 525 type Namer interface { 526 Name() string 527 } 528 529 And we need to make `Person` satisfy `Namer` 530 531 func (e Person) Name() string { return e.First + e.Last } 532 533 And the rest of the code still works: 534 535 e := Employee{Person{"John", "Doe", 49}} 536 537 * Easy mocking of interfaces 538 539 Given this function: 540 541 .code go4cpp/mock.go /func/,/^}/ 542 543 How would you test it? 544 545 * Easy mocking of interfaces 546 547 `net.Conn` is an interface defined in the `net` package of the standard library. 548 549 type Conn interface { 550 Read(b []byte) (n int, err error) 551 Write(b []byte) (n int, err error) 552 Close() error 553 LocalAddr() Addr 554 RemoteAddr() Addr 555 SetDeadline(t time.Time) error 556 SetReadDeadline(t time.Time) error 557 SetWriteDeadline(t time.Time) error 558 } 559 560 We need a fake `net.Conn`! 561 562 * One solution 563 564 We could define a new type that satisfies `net.Conn` 565 566 type fakeConn struct {} 567 568 func (c fakeConn) Read(b []byte) (n int, err error) {...} 569 func (c fakeConn) Write(b []byte) (n int, err error) {...} 570 func (c fakeConn) Close() error {...} 571 ... 572 573 But, is there a better way? 574 575 * The better way 576 577 .code go4cpp/mock.go /type fakeConn/,/end_fake/ 578 579 And our test can look like: 580 581 .play go4cpp/mock.go /func main/, 582 583 * Concurrency 584 585 * Concurrency 586 587 It is part of the language, not a library. 588 589 Based on three concepts: 590 591 - goroutines: lightweight threads 592 - channels: typed pipes used to communicate and synchronize between goroutines 593 - select: control structure to coordinate concurrent operations 594 595 .image go4cpp/funnelin.jpg 300 700 596 597 * Sleep and talk 598 599 .code go4cpp/conc1.go /sleepAndTalk/,/^}/ 600 601 We want a message per second. 602 603 .play go4cpp/conc1.go /func main/,/^}/ 604 605 What if we started all the `sleepAndTalk` concurrently? 606 607 Just add `go`! 608 609 * Concurrent sleep and talk 610 611 .play go4cpp/conc2.go /func main/,/^}/ 612 613 That was fast ... 614 615 When the `main` goroutine ends, the program ends. 616 617 * Concurrent sleep and talk with more sleeping 618 619 .play go4cpp/conc3.go /func main/,/^}/ 620 621 But synchronizing with `Sleep` is a bad idea. 622 623 * Communicating through channels 624 625 `sleepAndTalk` sends the string into the channel instead of printing it. 626 627 .code go4cpp/chan.go /sleepAndTalk/,/^}/ 628 629 We create the channel and pass it to `sleepAndTalk`, then wait for the values to be sent. 630 631 .play go4cpp/chan.go /func main/,/^}/ 632 633 * Aside: a web server 634 635 A production ready web server. 636 637 .play go4cpp/webserver.go 638 639 * Let's count on the web 640 641 Why is this wrong? 642 643 .play go4cpp/badcounter.go /nextID/, 644 645 * Let's count on the web correctly 646 647 We receive the next id from a channel. 648 649 .code go4cpp/goodcounter.go /nextID/,/^}/ 650 651 We need to send ids into the channel. 652 653 .code go4cpp/goodcounter.go /counter/,/^}/ 654 655 * Let's count on the web correctly 656 657 And we need to do both at the same time. 658 659 .play go4cpp/goodcounter.go /func main/,/^}/ 660 661 * Let's fight! 662 663 `select` allows us to choose among multiple channel operations. 664 665 .play go4cpp/battle.go /battle/,/^}/ 666 667 Go - [[http://localhost:8080/fight?usr=go]] 668 C++ - [[http://localhost:8080/fight?usr=cpp]] 669 670 * Chain of gophers 671 672 .image go4cpp/chain.jpg 673 674 Ok, I'm just bragging here 675 676 * Chain of gophers 677 678 .play go4cpp/goroutines.go /func f/, 679 680 * Concurrency is very powerful 681 682 And there's lots to learn! 683 684 - [[http://talks.golang.org/2012/concurrency.slide#1][Go Concurrency Patterns]], by Rob Pike 685 - [[http://talks.golang.org/2013/advconc.slide#1][Advanced Concurrency Patterns]], by Sameer Ajmani 686 - [[http://talks.golang.org/2012/waza.slide#1][Concurrency is not Parellelism]], by Rob Pike 687 688 .image go4cpp/busy.jpg 689 690 * In conclusion 691 692 - Go is simple, consistent, readable, and fun. 693 694 - All types are equal: methods on any type. 695 696 - Implicit satisfaction of interfaces makes code easier to reuse. 697 698 - Use composition instead of inheritance. 699 700 - Struct embedding is a powerful tool. 701 702 - Concurrency is awesome, and you should check it out. 703 704 * What to do next? 705 706 Learn Go on your browser with [[http://tour.golang.org][tour.golang.org]] 707 708 Find more about Go on [[http://golang.org][golang.org]] 709 710 Join the community at [[https://groups.google.com/forum/#!forum/Golang-nuts][golang-nuts]] 711 712 Link to the slides [[http://talks.golang.org/2015/go4cpp.slide]]