Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1552)

Side by Side Diff: 2014/go4gophers.slide

Issue 97780044: code review 97780044: go.talks: add "Go for Gophers" slides (Closed)
Patch Set: diff -r 2b96b82cd80d https://code.google.com/p/go.talks Created 9 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | 2014/go4gophers/chain.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 Go for gophers
2 GopherCon closing keynote
3 25 Apr 2014
4
5 Andrew Gerrand
6 adg@golang.org
7
8
9 * About me
10
11 .image go4gophers/gopherswim.jpg
12
13 I joined Google and the Go team in February 2010.
14
15 Had to re-think some of my preconceptions about programming.
16
17 Let me share what I have learned since.
18
19
20 * Interfaces
21
22
23 * Interfaces: first impressions
24
25 I used to think about classes and types.
26
27 Go resists this:
28
29 - No inheritance.
30 - No subtype polymorphism.
31 - No generics.
32
33 It instead emphasizes _interfaces_.
34
35
36 * Interfaces: the Go way
37
38 Go interfaces are small.
39
40 type Stringer interface {
41 String() string
42 }
43
44 A `Stringer` can pretty print itself.
45 Anything that implements `String` is a `Stringer`.
46
47
48 * An interface example
49
50 An `io.Reader` value emits a stream of binary data.
51
52 type Reader interface {
53 Read([]byte) (int, error)
54 }
55
56 Like a UNIX pipe.
57
58
59 * Implementing interfaces
60
61 .code go4gophers/reader.go /ByteReader/,/^}/
62
63
64 * Wrapping interfaces
65
66 .code go4gophers/reader.go /LogReader/,/STOP/
67
68 Wrapping a `ByteReader` with a `LogReader`:
69
70 .play go4gophers/reader.go /START/,/STOP/
71
72 By wrapping we compose interface _values_.
73
74
75 * Chaining interfaces
76
77 Wrapping wrappers to build chains:
78
79 .code go4gophers/chain.go /START/,/STOP/
80
81 More succinctly:
82
83 .play go4gophers/chain.go /LogReader{io/
84
85 Implement complex behavior by composing small pieces.
86
87
88 * Programming with interfaces
89
90 Interfaces separate data from behavior.
91
92 With interfaces, functions can operate on _behavior:_
93
94 // Copy copies from src to dst until either EOF is reached
95 // on src or an error occurs. It returns the number of bytes
96 // copied and the first error encountered while copying, if any.
97 func Copy(dst Writer, src Reader) (written int64, err error) {
98
99 .play go4gophers/chain.go /LogReader{io/
100
101 `Copy` can't know about the underlying data structures.
102
103
104 * A larger interface
105
106 `sort.Interface` describes the operations required to sort a collection:
107
108 type Interface interface {
109 Len() int
110 Less(i, j int) bool
111 Swap(i, j int)
112 }
113
114 `IntSlice` can sort a slice of ints:
115
116 type IntSlice []int
117
118 func (p IntSlice) Len() int { return len(p) }
119 func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
120 func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
121
122 `sort.Sort` uses can sort a `[]int` with `IntSlice`:
123
124 .play go4gophers/sort.go /START/,/STOP/
125
126
127 * Another interface example
128
129 The `Organ` type describes a body part and can print itself:
130
131 .play go4gophers/organs.go /type Organ/,$
132
133
134 * Sorting organs
135
136 The `Organs` type knows how to describe and mutate a slice of organs:
137
138 .code go4gophers/organs2.go /PART1/,/PART2/
139
140 The `ByName` and `ByWeight` types embed `Organs` to sort by different fields:
141
142 .code go4gophers/organs2.go /PART2/,/PART3/
143
144 With embedding we compose _types_.
145
146
147 * Sorting organs (continued)
148
149 To sort a `[]*Organ`, wrap it with `ByName` or `ByWeight` and pass it to `sort.S ort`:
150
151 .play go4gophers/organs2.go /START/,/STOP/
152
153
154 * Another wrapper
155
156 The `Reverse` function takes a `sort.Interface` and
157 returns a `sort.Interface` with an inverted `Less` method:
158
159 .code go4gophers/organs3.go /func Reverse/,$
160
161 To sort the organs in descending order, compose our sort types with `Reverse`:
162
163 .play go4gophers/organs3.go /START/,/STOP/
164
165
166 * Interfaces: why they work
167
168 These are not just cool tricks.
169
170 This is how we structure programs in Go.
171
172
173 * Interfaces: Sigourney
174
175 Sigourney is a modular audio synthesizer I wrote in Go.
176
177 .image go4gophers/sigourney.png
178
179 Audio is generated by a chain of `Processors`:
180
181 type Processor interface {
182 Process(buffer []Sample)
183 }
184
185 ([[https://github.com/nf/sigourney][github.com/nf/sigourney]])
186
187
188 * Interfaces: Roshi
189
190 Roshi is a time-series event store written by Peter Bourgon. It provides this AP I:
191 ········
192 Insert(key, timestamp, value)
193 Delete(key, timestamp, value)
194 Select(key, offset, limit) []TimestampValue
195
196 The same API is implemented by the `farm` and `cluster` parts of the system.
197
198 .image go4gophers/roshi.png
199
200 An elegant design that exhibits composition.
201 ([[https://github.com/soundcloud/roshi][github.com/soundcloud/roshi]])
202
203
204 * Interfaces: why they work (continued)
205
206 Interfaces are _the_ generic programming mechanism.
207
208 This gives all Go code a familiar shape.
209
210 Less is more.
211
212
213 * Interfaces: why they work (continued)
214
215 It's all about composition.
216
217 Interfaces—by design and convention—encourage us to write composable code.
218
219
220 * Interfaces: why they work (continued)
221
222 Interfaces types are just types
223 and interface values are just values.
224
225 They are orthogonal to the rest of the language.
226
227
228 * Interfaces: why they work (continued)
229
230 Interfaces separate data from behavior. (Classes conflate them.)
231
232 type HandlerFunc func(ResponseWriter, *Request)
233
234 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
235 f(w, r)
236 }
237
238
239 * Interfaces: what I learned
240
241 Think about composition.
242
243 Better to have many small simple things than one big complex thing.
244
245 Also: what I thought of as small is pretty big.
246
247 Some repetition in the small is okay when it benefits "the large".
248
249
250 * Concurrency
251
252
253 * Concurrency: first impressions
254
255 My first exposure to concurrency was in C, Java, and Python.
256 Later: event-driven models in Python and JavaScript.
257
258 When I saw Go I saw:
259
260 "The performance of an event-driven model without callback hell."
261
262 But I had questions: "Why can't I wait on or kill a goroutine?"
263
264
265 * Concurrency: the Go way
266
267 Goroutines provide concurrent execution.
268
269 Channels express the communication and synchronization of independent processes.
270
271 Select enables computation on channel operations.
272
273 .image go4gophers/gopherflag.png
274
275
276 * A concurrency example
277
278 The binary tree comparison exercise from the Go Tour.
279
280 "Implement a function
281
282 func Same(t1, t2 *tree.Tree) bool
283
284 that compares the contents of two binary trees."
285
286 .image go4gophers/tree.png
287
288
289 * Walking a tree
290
291 type Tree struct {
292 Left, Right *Tree
293 Value int
294 }
295
296 A simple depth-first tree traversal:
297
298 .play go4gophers/tree-walk.go /func Walk/,$
299
300
301 * Comparing trees (1/2)
302
303 A concurrent walker:
304
305 .code go4gophers/tree-thread.go /func Walk/,/STOP/
306
307
308 * Comparing trees (2/2)
309
310 Walking two trees concurrently:
311
312 .play go4gophers/tree-thread.go /func Same/,$
313
314
315 * Comparing trees without channels (1/3)
316
317 .code go4gophers/tree-nothread.go /func Same/,/^}/
318
319 The `Walk` function has nearly the same signature:
320
321 .code go4gophers/tree-nothread.go /func Walk/
322 .code go4gophers/tree-nothread.go /func.+Next/
323
324 (We call `Next` instead of the channel receive.)
325
326
327 * Comparing trees without channels (2/3)
328
329 But the implementation is much more complex:
330
331 .code go4gophers/tree-nothread.go /func Walk/,/CUT/
332
333
334 * Comparing trees without channels (3/3)
335
336 .code go4gophers/tree-nothread.go /CUT/,/STOP/
337
338
339 * Another look at the channel version
340
341 .code go4gophers/tree-thread.go /func Walk/,/STOP/
342
343 But there's a problem: when an inequality is found,
344 a goroutine might be left blocked sending to `ch`.
345
346
347 * Stopping early
348
349 Add a `quit` channel to the walker so we can stop it mid-stride.
350
351 .code go4gophers/tree-select.go /func Walk/,/STOP/
352
353
354 * Stopping early (continued)
355
356 Create a `quit` channel and pass it to each walker.
357 By closing `quit` when the `Same` exits, any running walkers are terminated.
358
359 .code go4gophers/tree-select.go /func Same/,/^}/
360
361
362 * Why not just kill the goroutines?
363
364 Goroutines are invisible to Go code. They can't be killed or waited on.
365
366 You have to build that yourself.
367
368 There's a reason:
369
370 As soon as Go code knows in which thread it runs you get thread-locality.
371
372 Thread-locality defeats the concurrency model.
373
374
375 * Concurrency: why it works
376
377 The model makes concurrent code easy to read and write.
378 (Makes concurrency is *accessible*.)
379
380 This encourages the decomposition of independent computations.
381
382
383 * Concurrency: why it works (continued)
384
385 The simplicity of the concurrency model makes it flexible.
386
387 Channels are just values; they fit right into the type system.
388
389 Goroutines are invisible to Go code; this gives you concurrency anywhere.
390
391 Less is more.
392
393
394 * Concurrency: what I learned
395
396 Concurrency is not just for doing more things faster.
397
398 It's for writing better code.
399
400
401 * Syntax
402
403
404 * Syntax: first impressions
405
406 At first, Go syntax felt a bit inflexible and verbose.
407
408 It affords few of the conveniences to which I was accustomed.
409
410 For instance:
411
412 - No getters/setters on fields.
413 - No map/filter/reduce/zip.
414 - No optional arguments.
415
416
417 * Syntax: the Go way
418
419 Favor readability above all.
420
421 Offer enough sugar to be productive, but not too much.
422
423
424 * Getters and setters (or "properties")
425
426 Getters and setters turn assignments and reads into function calls.
427 This leads to surprising hidden behavior.
428
429 In Go, just write (and call) the methods.
430
431 The control flow cannot be obscured.
432
433
434 * Map/filter/reduce/zip
435
436 Map/filter/reduce/zip are useful in Python.
437
438 a = [1, 2, 3, 4]
439 b = map(lambda x: x+1, a)
440
441 In Go, you just write the loops.
442
443 a := []int{1, 2, 3, 4}
444 b := make([]int, len(a))
445 for i, x := range a {
446 b[i] = x+1
447 }
448
449 This is a little more verbose,
450 but makes the performance characteristics obvious.
451
452 It's easy code to write, and you get more control.
453
454
455 * Optional arguments
456
457 Go functions can't have optional arguments.
458
459 Instead, use variations of the function:
460
461 func NewWriter(w io.Writer) *Writer
462 func NewWriterLevel(w io.Writer, level int) (*Writer, error)
463
464 Or an options struct:
465
466 func New(o *Options) (*Jar, error)
467
468 type Options struct {
469 PublicSuffixList PublicSuffixList
470 }
471
472 Or a variadic list of options.
473
474 Create many small simple things, not one big complex thing.
475
476
477 * Syntax: why it works
478
479 The language resists convoluted code.
480
481 With obvious control flow, it's easy to navigate unfamiliar code.
482
483 Instead we create more small things that are easy to document and understand.
484
485 So Go code is easy to read.
486
487 (And with gofmt, it's easy to write readable code.)
488
489
490 * Syntax: what I learned
491
492 I was often too clever for my own good.
493
494 I appreciate the consistency, clarity, and _transparency_ of Go code.
495
496 I sometimes miss the conveniences, but rarely.
497
498
499 * Error handling
500
501
502 * Error handling: first impressions
503
504 I had previously used exceptions to handle errors.
505
506 Go's error handling model felt verbose by comparison.
507
508 I was immediately tired of typing this:
509
510 if err != nil {
511 return err
512 }
513
514
515 * Error handling: the Go way
516
517 Go codifies errors with the built-in `error` interface:
518
519 type error interface {
520 Error() string
521 }
522
523 Error values are used just like any other value.
524
525 func doSomething() error
526
527 err := doSomething()
528 if err != nil {
529 log.Println("An error occurred:", err)
530 }
531
532 Error handling code is just code.
533
534 (Started as a convention (`os.Error`). We made it built in for Go 1.)
535
536
537 * Error handling: why it works
538
539 Error handling is important.
540
541 Go makes error handling as important as any other code.
542
543
544 * Error handling: why it works (continued)
545
546 Errors are just values; they fit easily into the rest of the language
547 (interfaces, channels, and so on).
548
549 Result: Go code handles errors correctly and elegantly.
550
551
552 * Error handling: why it works (continued)
553
554 We use the same language for errors as everything else.
555
556 Lack of hidden control flow (throw/try/catch/finally) improves readability.
557
558 Less is more.
559
560
561
562 * Error handling: what I learned
563
564 To write good code we must think about errors.
565
566 Exceptions make it easy to avoid thinking about errors.
567 (Errors shouldn't be "exceptional!")
568
569 Go encourages us to consider every error condition.
570
571 My Go programs are far more robust than my programs in other languages.
572
573 I don't miss exceptions at all.
574
575
576 * Packages
577
578
579 * Packages: first impressions
580
581 I found the capital-letter-visibility rule weird;
582 "Let me use my own naming scheme!"
583
584 I didn't like "package per directory";
585 "Let me use my own structure!"
586
587 I was disappointed by lack of monkey patching.
588
589
590 * Packages: the Go way
591
592 Go packages are a name space for types, functions, variables, and constants.
593
594
595 * Visibility
596
597 Visibility is at the package level.
598 Names are "exported" when they begin with a capital letter.
599
600 package zip
601
602 func NewReader(r io.ReaderAt, size int64) (*Reader, error) // exported
603
604 type Reader struct { // exported
605 File []*File // exported
606 Comment string // exported
607 r io.ReaderAt // unexported
608 }
609
610 func (f *File) Open() (rc io.ReadCloser, err error) // exported
611
612 func (f *File) findBodyOffset() (int64, error) // unexported
613
614 func readDirectoryHeader(f *File, r io.Reader) error // unexported
615
616 Good for readability: easy to see whether a name is part of the public interface .
617 Good for design: couples naming decisions with interface decisions.
618
619
620 * Package structure
621
622 Packages can be spread across multiple files.
623
624 Permits shared private implementation and informal code organization.
625
626 Packages files must live in a directory unique to the package.
627
628 The path to that directory determines the package's import path.
629
630 The build system locates dependencies from the source alone.
631
632
633 * "Monkey patching"
634
635 Go forbids modifying package declarations from outside the package.
636
637 But we can get similar behavior using global variables:
638
639 package flag
640
641 var Usage = func() {
642 fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
643 PrintDefaults()
644 }
645
646 Or registration functions:
647
648 package http
649
650 func Handle(pattern string, handler Handler)
651
652 This gives the flexibility of monkey patching but on the package author's terms.
653
654 (This depends on Go's initialization semantics.)
655
656
657 * Packages: why they work
658
659 The loose organization of packages lets us write and refactor code quickly.
660
661 But packages encourage the programmer to consider the public interface.
662
663 This leads to good names and simpler interfaces.
664
665 With the source as the single source of truth,
666 there are no makefiles to get out of sync.
667
668 (This design enables great tools like [[http://godoc.org][godoc.org]] and goimpo rts.)
669
670 Predictable semantics make packages easy to read, understand, and use.
671
672
673 * Packages: what I learned
674
675 Go's package system taught me to prioritize the consumer of my code.
676 (Even if that consumer is me.)
677
678 It also stopped me from doing gross stuff.
679
680 Packages are rigid where it matters, and loose where it doesn't.
681 It just feels right.
682
683 Probably my favorite part of the language.
684
685
686 * Documentation
687
688
689 * Documentation: first impressions
690
691 Godoc reads documentation from Go source code, like `pydoc` or `javadoc`.
692
693 But unlike those two, it doesn't support complex formatting or other meta data.
694 Why?
695
696
697 * Documentation: the Go way
698
699 Godoc comments precede the declaration of an exported identifier:
700
701 // Join concatenates the elements of a to create a single string.
702 // The separator string sep is placed between elements in the resulting string.
703 func Join(a []string, sep string) string {
704
705 It extracts the comments and presents them:
706
707 $ godoc strings Join
708 func Join(a []string, sep string) string
709 Join concatenates the elements of a to create a single string. The
710 separator string sep is placed between elements in the resulting str ing.
711
712 Also integrated with the testing framework to provide testable example functions .
713
714 func ExampleJoin() {
715 s := []string{"foo", "bar", "baz"}
716 fmt.Println(strings.Join(s, ", "))
717 // Output: foo, bar, baz
718 }
719
720
721 * Documentation: the Go way (continued)
722
723 .image go4gophers/godoc.png
724
725
726 * Documentation: why it works
727
728 Godoc wants you to write good comments, so the source looks great:
729
730 // ValidMove reports whether the specified move is valid.
731 func ValidMove(from, to Position) bool
732
733 Javadoc just wants to produce pretty documentation, so the source is hideous:
734
735 /**
736 * Validates a chess move.
737 *
738 * @param fromPos position from which a piece is being moved
739 * @param toPos position to which a piece is being moved
740 * @return true if the move is valid, otherwise false
741 */
742 boolean isValidMove(Position fromPos, Position toPos)
743
744 (Also a grep for `"ValidMove"` will return the first line of documentation.)
745
746
747 * Documentation: what I learned
748
749 Godoc taught me to write documentation _as_I_code._
750
751 Writing documentation _improves_the_code_ I write.
752
753
754 * More
755
756 There are many more examples.
757
758 The overriding theme:
759
760 - At first, something seemed weird or lacking.
761 - I realized it was a design decision.
762
763 Those decisions make the language—and Go code—better.
764
765 Sometimes you have to live with the language a while to see it.
766
767
768 * Lessons
769
770
771 * Code is communication
772
773 Be articulate:
774
775 - Choose good names.
776 - Design simple interfaces.
777 - Write precise documentation.
778 - Don't be too clever.
779
780
781 * Less is exponentially more
782
783 New features can weaken existing features.
784
785 Features multiply complexity.
786
787 Complexity defeats orthogonality.
788
789 Orthogonality is vital: it enables composition.
790
791
792 * Composition is key
793
794 Don't solve problems by building _a_ thing.
795
796 Instead, combine simple tools and compose them.
797
798
799 * Design good interfaces
800
801 .image go4gophers/gophertraining.png
802
803 .html go4gophers/gophertraining.html
804
805
806 * Simplicity is hard
807
808 Invest the time to find the simple solution.
809
810
811 * Go's effect on me
812
813 These lessons were all things I already "knew".
814
815 Go helped me internalize them.
816
817 .image go4gophers/gopherhat.jpg
818
819 Go made me a better programmer.
820
821
822 * A message for gophers everywhere
823
824 Let's build small, simple, and beautiful things together.
825
826 .image go4gophers/gopherswrench.jpg
827
OLDNEW
« no previous file with comments | « no previous file | 2014/go4gophers/chain.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b