A Recovering
Java Developer Learns to Go
Matt Stine (@mstine)
Cloud Foundry Platform Engineer at Pivotal
matt.stine@gmail....
I am not a Go expert.
I’m just learning to Go.
CF Architecture - January 2013
DEA Pool
Router
Cloud Controller
BOSH Director BOSH Agent
UAA/Login Servers Health Manager
...
CF Architecture - January 2014
Ruby
Java/Spring
Go
Loggregator
DEA Pool (Diego - Coming soon!)
Router
Cloud Controller
BOS...
–Matt Stine
“Hey, wait! I just got done learning Ruby!”
• Mike Gehard: “Go Within Cloud Foundry”

https://www.youtube.com/watch?v=d5aHr8VGU-8
• Onsi Fakhouri: “Diego: Re-envision...
✓ Hello World
✓ Why Go?
✓ Contrasts with Java:
- Features and Idioms
- Packaging / Modularity
- Types / OOP / Interfaces
-...
package main
!
import (
"fmt"
)
!
func main() {
fmt.Println("Hello World")
}
Hello World
All code goes
in a package.
Give ...
Why Go?
Iron Triangle of Language Design
EfficientCompilation
Ease of Programming
EfficientExecution
Systems
Programming
• 2007-09-21: Go invented at Google by Robert Griesemer, Rob Pike, and
Ken Thompson
• 2009-11-10: Go released as OSS
• 201...
Software Engineering in the LARGE
http://talks.golang.org/2012/splash.article
“Go is a programming language designed by Go...
Software Engineering in the LARGE
http://talks.golang.org/2012/splash.article
“Go is a programming language designed by Go...
✓ Safety and efficiency of a

statically-typed, compiled language
✓ Productivity and feel of a dynamic,

interpreted langua...
https://www.flickr.com/photos/slackpics/4289782818
A
Kit
for
Systems
Software
https://www.flickr.com/photos/pmiaki/6657150957
Differences from Java
https://www.flickr.com/photos/yukop/6778321940
• Features and Idioms
• Packaging / Modularity
• Types / OOP / Interfaces
• Concurrency
Contrasts with Java
Features
and
Idioms
https://www.flickr.com/photos/yukop/6778321940
Multiple Return Values
func vals() (int, int) {
return 3, 7
}
!
func main() {
a, b := vals()
fmt.Println(a)
fmt.Println(b)...
Closures
func intSeq() func() int {
i := 0
return func() int {
i += 1
return i
}
}
GBE
Closes over this state.
Closures
func main() {
nextInt := intSeq()
!
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
!
newInt...
Where’s my java.util.List? Slices
s := make([]string, 3)
fmt.Println("emp:", s)
!
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Pri...
Where’s my java.util.List? Slices
c := make([]string, len(s))
copy(c, s)
fmt.Println("cpy:", c)
!
l := s[2:5]
fmt.Println(...
Where’s my java.util.Map? Maps
m := make(map[string]int)
!
m["k1"] = 7
m["k2"] = 13
!
fmt.Println("map:", m)
!
v1 := m["k1...
Where’s my java.util.Map? Maps
delete(m, "k2")
fmt.Println("map:", m)
!
_, prs := m["k2"]
fmt.Println("prs:", prs)
!
n := ...
Looping with Range
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
!
for ...
We don’t need no stinkin’ exceptions…
func f1(arg int) (int, error) {
if arg == 42 {
return -1, errors.New("can't work wit...
(Semi)automatic Resource Management
func createFile(p string) *os.File {
fmt.Println("creating")
f, err := os.Create(p)
if...
(Semi)automatic Resource Management
func main() {
f := createFile("/tmp/defer.txt")
defer closeFile(f)
writeFile(f)
}
Run ...
Packaging/Modularity
https://www.flickr.com/photos/yukop/6778321940
TL;DR
COMPLEX
SIMPLE
• Every class in a package
• Import classes explicitly
- import java.util.Map
• Import all classes in a package
- import j...
• All types and functions belong to a package.
• Every source file must declare its package.
• Import packages to gain acce...
• public - any class in same package, or any importing class in a different
package, can see
• default (“package private”)...
• exported - any code in an importing file can see
- exported names start with uppercase letter
- func Copy(src *[]byte, de...
• Conventional correspondence to directory paths (e.g. com.ms.foo
should be at src/com/ms/foo) - tools expect this!
• Pack...
• Conventional correspondence to directory paths (e.g. github.com/go-martini/
martini should be at src/github.com/go-marti...
• Java admits:
- circular package dependencies
- dead imports
• Go rejects:
- circular package dependencies
- dead imports...
Types/OOP/Interfaces
https://www.flickr.com/photos/yukop/6778321940
For realz this time…
structs FTW
type Point struct {
X, Y float64
}
Define a type.
Give it a name.
This type is a struct.
(you can actually defin...
Methods are Functions!
func (p Point) Translate(xDist float64, yDist float64) Point {
return Point{p.X + xDist, p.Y + yDis...
composition FTW
type Point struct {
X, Y float64
}
!
const (
BLUE = iota
RED = iota
GREEN = iota
)
!
type ColorPoint struc...
• I have Points.
• I have ColorPoints.
• ColorPoints are like Points, but they are not Points.
• But I want to compute the...
Interfaces Group Behaviors
type Positioner interface {
Coordinates() Point
}
!
type Distancer interface {
DistanceTo(p Pos...
It’s all about satisfaction…
Java = explicit
!
Go = implicit
Calculating Distance
func distanceBetween(a Positioner, b Positioner)
float64 {
p := a.Coordinates()
q := b.Coordinates()
...
Point Satisfies Distancer and Positioner
func (p Point) Coordinates() Point {
return p
}
!
func (p Point) DistanceTo(pos Po...
ColorPoint Satisfies Distancer and Positioner
func (cp ColorPoint) Coordinates() Point {
return cp.Point
}
!
func (cp Color...
Behavior Not Taxonomy
Animal Satisfies Distancer and Positioner
func (a Animal) Coordinates() point.Point {
return point.Point{X: a.X, Y: a.Y}
}
...
Go!
p = point.Point{X: 1, Y: 2}
q := point.ColorPoint{Point: point.Point{X: 1, Y: 4},
Color: point.BLUE}
!
fmt.Printf("Dis...
Concurrency
https://www.flickr.com/photos/yukop/6778321940
• Parallelism = leveraging simultaneous execution of work to perform
many things at once. Limited to number of processors/...
• Java
- Threads
- OS managed
- Share address space with other threads in same process
• Go
- Goroutines
- user-space mana...
• Java
- Shared memory
- Locking
• Go
- Can share memory (see http://golang.org/pkg/sync)
- But there is a better way!
Syn...
– http://golang.org/doc/effective_go.html
“Do not communicate by sharing memory; instead,
share memory by communicating.”
Goroutines
func f(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, ":", i)
}
}
!
func main() {
f("direct")
!
go f...
Channels
func main() {
messages := make(chan string)
!
go func() { messages <- "ping" }()
!
msg := <-messages
fmt.Println(...
Channel Buffering
func main() {
messages := make(chan string, 2)
!
messages <- "buffered"
messages <- "channel"
!
fmt.Prin...
Channel Synchronization
func worker(done chan bool) {
fmt.Print("working...")
time.Sleep(time.Second)
fmt.Println("done")
...
Select
c1 := make(chan string)
c2 := make(chan string)
!
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
go func()...
Select
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("...
Closing Channels
jobs := make(chan int, 5)
done := make(chan bool)
!
go func() {
for {
j, more := <-jobs
if more {
fmt.Pri...
Closing Channels
for j := 1; j <= 3; j++ {
jobs <- j
fmt.Println("sent job", j)
}
close(jobs)
fmt.Println("sent all jobs")...
Range Over Channels
func main() {
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
close(queue)
!
for elem := r...
• Features and Idioms
• Packaging / Modularity
• Types / OOP / Interfaces
• Concurrency
Contrasts with Java
Thank You!!!
Matt Stine (@mstine)
Cloud Foundry Platform Engineer at Pivotal
matt.stine@gmail.com
http://www.mattstine.com...
Code samples marked “GBE” at https://gobyexample.com are by Mark McGranaghan and are Creative Commons Attribution 3.0
Unpo...
A Recovering Java Developer Learns to Go
A Recovering Java Developer Learns to Go
A Recovering Java Developer Learns to Go
Upcoming SlideShare
Loading in...5
×

A Recovering Java Developer Learns to Go

10,752

Published on

As presented at OSCON 2014.

The Go programming language has emerged as a favorite tool of DevOps and cloud practitioners alike. In many ways, Go is more famous for what it doesn’t include than what it does, and co-author Rob Pike has said that Go represents a “less is more” approach to language design.

The Cloud Foundry engineering teams have steadily increased their use of Go for building components, starting with the Router, and progressing through Loggregator, the CLI, and more recently the Health Manager. As a “recovering-Java-developer-turned-DevOps-junkie” focused on helping our customers and community succeed with Cloud Foundry, it became very clear to me that I needed to add Go to my knowledge portfolio.

This talk will introduce Go and its distinctives to Java developers looking to add Go to their toolkits. We’ll cover Go vs. Java in terms of:

* type systems
* modularity
* programming idioms
* object-oriented constructs
* concurrency

2 Comments
39 Likes
Statistics
Notes
No Downloads
Views
Total Views
10,752
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
232
Comments
2
Likes
39
Embeds 0
No embeds

No notes for slide

Transcript of "A Recovering Java Developer Learns to Go"

  1. 1. A Recovering Java Developer Learns to Go Matt Stine (@mstine) Cloud Foundry Platform Engineer at Pivotal matt.stine@gmail.com http://www.mattstine.com OFFICE HOURS Wednesday, 2:30 - 3:10 PM Expo Hall (Table A)
  2. 2. I am not a Go expert.
  3. 3. I’m just learning to Go.
  4. 4. CF Architecture - January 2013 DEA Pool Router Cloud Controller BOSH Director BOSH Agent UAA/Login Servers Health Manager Service Broker Node(s) Messaging (NATS) CLI Client Ruby Java/Spring Go
  5. 5. CF Architecture - January 2014 Ruby Java/Spring Go Loggregator DEA Pool (Diego - Coming soon!) Router Cloud Controller BOSH Director BOSH Agent UAA/Login Servers Health Manager Service Broker Node(s) Messaging (NATS) CLI Client
  6. 6. –Matt Stine “Hey, wait! I just got done learning Ruby!”
  7. 7. • Mike Gehard: “Go Within Cloud Foundry”
 https://www.youtube.com/watch?v=d5aHr8VGU-8 • Onsi Fakhouri: “Diego: Re-envisioning the Elastic Runtime”
 https://www.youtube.com/watch?v=1OkmVTFhfLY Go in Cloud Foundry
  8. 8. ✓ Hello World ✓ Why Go? ✓ Contrasts with Java: - Features and Idioms - Packaging / Modularity - Types / OOP / Interfaces - Concurrency Agenda
  9. 9. package main ! import ( "fmt" ) ! func main() { fmt.Println("Hello World") } Hello World All code goes in a package. Give access to exported stuff from other packages. Function definition, main() is entrypoint. Call an exported function!
  10. 10. Why Go?
  11. 11. Iron Triangle of Language Design EfficientCompilation Ease of Programming EfficientExecution Systems Programming
  12. 12. • 2007-09-21: Go invented at Google by Robert Griesemer, Rob Pike, and Ken Thompson • 2009-11-10: Go released as OSS • 2012-03-28: Go 1.0 is Released A History Lesson
  13. 13. Software Engineering in the LARGE http://talks.golang.org/2012/splash.article “Go is a programming language designed by Google to help solve Google's problems, and Google has big problems.”
  14. 14. Software Engineering in the LARGE http://talks.golang.org/2012/splash.article “Go is a programming language designed by Google to help solve Google's problems, and Google has big problems.”
  15. 15. ✓ Safety and efficiency of a
 statically-typed, compiled language ✓ Productivity and feel of a dynamic,
 interpreted language ✓ Address modern compute environments: - Multicore Processors - Networked Systems - Massive Computational Clusters - Web Programming Model Goals
  16. 16. https://www.flickr.com/photos/slackpics/4289782818
  17. 17. A Kit for Systems Software https://www.flickr.com/photos/pmiaki/6657150957
  18. 18. Differences from Java https://www.flickr.com/photos/yukop/6778321940
  19. 19. • Features and Idioms • Packaging / Modularity • Types / OOP / Interfaces • Concurrency Contrasts with Java
  20. 20. Features and Idioms https://www.flickr.com/photos/yukop/6778321940
  21. 21. Multiple Return Values func vals() (int, int) { return 3, 7 } ! func main() { a, b := vals() fmt.Println(a) fmt.Println(b) ! _, c := vals() fmt.Println(c) } GBE Return a pair of values. I Ignore the first value returned. Assign to multiple variables.
  22. 22. Closures func intSeq() func() int { i := 0 return func() int { i += 1 return i } } GBE Closes over this state.
  23. 23. Closures func main() { nextInt := intSeq() ! fmt.Println(nextInt()) fmt.Println(nextInt()) fmt.Println(nextInt()) ! newInts := intSeq() fmt.Println(newInts()) } GBE Captures its own value for i. Increments own value of i. Captures the value of i again! And increments it.
  24. 24. Where’s my java.util.List? Slices s := make([]string, 3) fmt.Println("emp:", s) ! s[0] = "a" s[1] = "b" s[2] = "c" fmt.Println("set:", s) fmt.Println("get:", s[2]) ! s = append(s, "d") s = append(s, "e", "f") fmt.Println("apd:", s) GBE Create an empty slice of strings (zero-valued). Set value at index. Get value at index. Append function (not mutate in-place!).
  25. 25. Where’s my java.util.List? Slices c := make([]string, len(s)) copy(c, s) fmt.Println("cpy:", c) ! l := s[2:5] fmt.Println("sl1:", l) ! l = s[:5] fmt.Println("sl2:", l) ! t := []string{"g", "h", "i"} fmt.Println("dcl:", t) GBE Length function. Copy function. Slicing function: index 2 (inclusive) to index 5 (exclusive). Slicing function: index 0 (inclusive) to index 5 (exclusive). Slice literals!
  26. 26. Where’s my java.util.Map? Maps m := make(map[string]int) ! m["k1"] = 7 m["k2"] = 13 ! fmt.Println("map:", m) ! v1 := m["k1"] fmt.Println("v1: ", v1) ! fmt.Println("len:", len(m)) Create an empty map of string ! int. Put values. Get value. Length function. GBE
  27. 27. Where’s my java.util.Map? Maps delete(m, "k2") fmt.Println("map:", m) ! _, prs := m["k2"] fmt.Println("prs:", prs) ! n := map[string]int{"foo": 1, "bar": 2} fmt.Println("map:", n) Delete function. Optional second return indicating “presence.” Map literals! GBE
  28. 28. Looping with Range nums := []int{2, 3, 4} sum := 0 for _, num := range nums { sum += num } fmt.Println("sum:", sum) ! for i, num := range nums { if num == 3 { fmt.Println("index:", i) } } ! kvs := map[string]string{"a": "apple", "b": "banana"} for k, v := range kvs { fmt.Printf("%s -> %sn", k, v) } Discard first (index), sum second (value). Keep both returns! With maps, first = key, second = value. GBE
  29. 29. We don’t need no stinkin’ exceptions… func f1(arg int) (int, error) { if arg == 42 { return -1, errors.New("can't work with 42") } return arg + 3, nil } ! func main() { for _, i := range []int{7, 42} { if r, e := f1(i); e != nil { fmt.Println("f1 failed:", e) } else { fmt.Println("f1 worked:", r) } } } Conventional: last return is error. Makes an error with the provided message. Return nil if there was no error. Idiomatic inline error check. GBE
  30. 30. (Semi)automatic Resource Management func createFile(p string) *os.File { fmt.Println("creating") f, err := os.Create(p) if err != nil { panic(err) } return f } func writeFile(f *os.File) { fmt.Println("writing") fmt.Fprintln(f, "data") ! } ! func closeFile(f *os.File) { fmt.Println("closing") f.Close() } GBE
  31. 31. (Semi)automatic Resource Management func main() { f := createFile("/tmp/defer.txt") defer closeFile(f) writeFile(f) } Run after the function completes. GBE
  32. 32. Packaging/Modularity https://www.flickr.com/photos/yukop/6778321940
  33. 33. TL;DR COMPLEX SIMPLE
  34. 34. • Every class in a package • Import classes explicitly - import java.util.Map • Import all classes in a package - import java.util.* • Statically import class static members: - import static java.lang.Math.PI - import static java.lang.Math.* Java Packaging
  35. 35. • All types and functions belong to a package. • Every source file must declare its package. • Import packages to gain access to exported members. Go Packaging
  36. 36. • public - any class in same package, or any importing class in a different package, can see • default (“package private”) - any class in same package can see • protected - any class in same package, or any subclass in a different package, can see • private - no class other than this can see • Scope indicated by prefixing name at declaration time. Java Scoping
  37. 37. • exported - any code in an importing file can see - exported names start with uppercase letter - func Copy(src *[]byte, dest *[]byte) • non-exported - only code in the same package can see - non-exported names start with _ or lowercase letter - func copy(src *[]byte, dest *[]byte) - func _Copy(src *[]byte, dest *[]byte) Go Scoping
  38. 38. • Conventional correspondence to directory paths (e.g. com.ms.foo should be at src/com/ms/foo) - tools expect this! • Package paths do not have to be unique at compile or runtime (first dependency found/loaded wins!) • Conventional correspondence to URL of author (e.g. my domain is www.mattstine.com, so my packages names start with com.mattstine) - but no actual relationship to source code location! Java Naming
  39. 39. • Conventional correspondence to directory paths (e.g. github.com/go-martini/ martini should be at src/github.com/go-martini/martini) - tools expect this! • Package paths MUST BE UNIQUE across a $GOPATH. • Package names do not have to be unique. • Referring to imported names must be qualified by package name (e.g. sql.DB not just DB)… can locally alias (e.g. import dbstuff “database/sql”) • Conventional correspondence to URL of code location (e.g. import http://github.com/ joefitzgerald/cfenv as import “github.com/joefitzgerald/cfenv"). • Can “go get” remote packages - supports Git, SVN, Mercurial, Bazaar. Go Naming
  40. 40. • Java admits: - circular package dependencies - dead imports • Go rejects: - circular package dependencies - dead imports Miscellany
  41. 41. Types/OOP/Interfaces https://www.flickr.com/photos/yukop/6778321940
  42. 42. For realz this time…
  43. 43. structs FTW type Point struct { X, Y float64 } Define a type. Give it a name. This type is a struct. (you can actually define others!) Add stuff! (upcase exports apply here too!)
  44. 44. Methods are Functions! func (p Point) Translate(xDist float64, yDist float64) Point { return Point{p.X + xDist, p.Y + yDist} } Receiver argument! Can define methods on pointers or values.
  45. 45. composition FTW type Point struct { X, Y float64 } ! const ( BLUE = iota RED = iota GREEN = iota ) ! type ColorPoint struct { Point Point Color int } Define an enumerated constant (closest to Java enum). A ColorPoint has-a Point!
  46. 46. • I have Points. • I have ColorPoints. • ColorPoints are like Points, but they are not Points. • But I want to compute the euclidean distance between them. • What to do? Problem
  47. 47. Interfaces Group Behaviors type Positioner interface { Coordinates() Point } ! type Distancer interface { DistanceTo(p Positioner) float64 }
  48. 48. It’s all about satisfaction… Java = explicit ! Go = implicit
  49. 49. Calculating Distance func distanceBetween(a Positioner, b Positioner) float64 { p := a.Coordinates() q := b.Coordinates() sqOfXDist := math.Pow(p.X-q.X, 2) sqOfYDist := math.Pow(p.Y-q.Y, 2) return math.Sqrt(sqOfXDist + sqOfYDist) }
  50. 50. Point Satisfies Distancer and Positioner func (p Point) Coordinates() Point { return p } ! func (p Point) DistanceTo(pos Positioner) float64 { return distanceBetween(p, pos) }
  51. 51. ColorPoint Satisfies Distancer and Positioner func (cp ColorPoint) Coordinates() Point { return cp.Point } ! func (cp ColorPoint) DistanceTo(pos Positioner) float64 { return distanceBetween(cp, pos) }
  52. 52. Behavior Not Taxonomy
  53. 53. Animal Satisfies Distancer and Positioner func (a Animal) Coordinates() point.Point { return point.Point{X: a.X, Y: a.Y} } ! func (a Animal) DistanceTo(pos point.Positioner) float64 { thing := pos.Coordinates() sqOfXDist := math.Pow(a.X-thing.X, 2) sqOfYDist := math.Pow(a.Y-thing.Y, 2) return math.Sqrt(sqOfXDist + sqOfYDist) }
  54. 54. Go! p = point.Point{X: 1, Y: 2} q := point.ColorPoint{Point: point.Point{X: 1, Y: 4}, Color: point.BLUE} ! fmt.Printf("Dist b/w p and q = %vn", p.DistanceTo(q)) fmt.Printf("Dist b/w q and p = %vn", q.DistanceTo(p)) ! penguin := animal.Animal{Name: "penguin", X: 1, Y: 1} seal := animal.Animal{Name: "seal", X: 1, Y: 4} ! fmt.Printf("Dist b/w penguin and seal = %vn", penguin.DistanceTo(seal)) fmt.Printf("Dist b/w penguin and point = %vn", penguin.DistanceTo(p))
  55. 55. Concurrency https://www.flickr.com/photos/yukop/6778321940
  56. 56. • Parallelism = leveraging simultaneous execution of work to perform many things at once. Limited to number of processors/cores you have. • Concurrency = composition of work to manage many things at once. No theoretical limit. • Rob Pike: “Concurrency is Not Parallelism”
 http://www.youtube.com/watch?v=cN_DpYBzKso Concurrency vs Parallelism
  57. 57. • Java - Threads - OS managed - Share address space with other threads in same process • Go - Goroutines - user-space managed by language runtime - multiplexed onto pool of OS threads Parallelism - How?
  58. 58. • Java - Shared memory - Locking • Go - Can share memory (see http://golang.org/pkg/sync) - But there is a better way! Synchronization?
  59. 59. – http://golang.org/doc/effective_go.html “Do not communicate by sharing memory; instead, share memory by communicating.”
  60. 60. Goroutines func f(from string) { for i := 0; i < 3; i++ { fmt.Println(from, ":", i) } } ! func main() { f("direct") ! go f("goroutine") ! go func(msg string) { fmt.Println(msg) }("going") } GBE Synchronous Asynchronous Asynchronous and Anonymous
  61. 61. Channels func main() { messages := make(chan string) ! go func() { messages <- "ping" }() ! msg := <-messages fmt.Println(msg) } GBE Create a new channel. Sending Receiving
  62. 62. Channel Buffering func main() { messages := make(chan string, 2) ! messages <- "buffered" messages <- "channel" ! fmt.Println(<-messages) fmt.Println(<-messages) } GBE Make a channel that will buffer two values. Send twice Receive twice
  63. 63. Channel Synchronization func worker(done chan bool) { fmt.Print("working...") time.Sleep(time.Second) fmt.Println("done") done <- true } ! func main() { done := make(chan bool, 1) go worker(done) <-done } GBE Notify receive that I’m done. Run worker on a goroutine, pass “done” channel. Block until msg received!
  64. 64. Select c1 := make(chan string) c2 := make(chan string) ! go func() { time.Sleep(time.Second * 1) c1 <- "one" }() go func() { time.Sleep(time.Second * 2) c2 <- "two" }() GBE Create two channels. Create two goroutines; each sends message to different channel.
  65. 65. Select for i := 0; i < 2; i++ { select { case msg1 := <-c1: fmt.Println("received", msg1) case msg2 := <-c2: fmt.Println("received", msg2) } } GBE Await both messages simultaneously! Print each as it arrives!
  66. 66. Closing Channels jobs := make(chan int, 5) done := make(chan bool) ! go func() { for { j, more := <-jobs if more { fmt.Println("received job", j) } else { fmt.Println("received all jobs") done <- true return } } }() GBE Job channel for sending work. Done channel to indicate all work complete. Receive jobs - more will be false if jobs is closed. If no more jobs, say that I’m done!
  67. 67. Closing Channels for j := 1; j <= 3; j++ { jobs <- j fmt.Println("sent job", j) } close(jobs) fmt.Println("sent all jobs") ! <-done GBE Send the jobs to the worker. Close the jobs channel. Block until the worker is finished.
  68. 68. Range Over Channels func main() { queue := make(chan string, 2) queue <- "one" queue <- "two" close(queue) ! for elem := range queue { fmt.Println(elem) } } GBE Pull messages off channel for each iteration of the loop.
  69. 69. • Features and Idioms • Packaging / Modularity • Types / OOP / Interfaces • Concurrency Contrasts with Java
  70. 70. Thank You!!! Matt Stine (@mstine) Cloud Foundry Platform Engineer at Pivotal matt.stine@gmail.com http://www.mattstine.com OFFICE HOURS Wednesday, 2:30 - 3:10 PM Expo Hall (Table A)
  71. 71. Code samples marked “GBE” at https://gobyexample.com are by Mark McGranaghan and are Creative Commons Attribution 3.0 Unported licensed (http://creativecommons.org/licenses/by/3.0). ! The Go Gopher logo was created by Renee French and is Creative Commons Attribution 3.0 Unported licensed (http:// creativecommons.org/licenses/by/3.0). ! The Java Duke logo is BSD licensed (http://opensource.org/licenses/bsd-license.php).
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×