+ All Categories
Transcript
Page 1: A Recovering Java Developer Learns to Go

A Recovering Java Developer Learns to Go

Matt Stine (@mstine) Cloud Foundry Platform Engineer at Pivotal

[email protected] http://www.mattstine.com

OFFICE HOURS Wednesday, 2:30 - 3:10 PM

Expo Hall (Table A)

Page 2: A Recovering Java Developer Learns to Go

I am not a Go expert.

Page 3: A Recovering Java Developer Learns to Go

I’m just learning to Go.

Page 4: A Recovering Java Developer Learns to Go

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

Page 5: A Recovering Java Developer Learns to Go

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

Page 6: A Recovering Java Developer Learns to Go

–Matt Stine

“Hey, wait! I just got done learning Ruby!”

Page 7: A Recovering Java Developer Learns to Go

• 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

Page 8: A Recovering Java Developer Learns to Go

✓Hello World ✓Why Go? ✓Contrasts with Java:

- Features and Idioms - Packaging / Modularity - Types / OOP / Interfaces - Concurrency

Agenda

Page 9: A Recovering Java Developer Learns to Go

package main !import ( "fmt" ) !func main() { fmt.Println("Hello World") }

Hello WorldAll code goes in a package.

Give access to exported

stuff from other packages.

Function definition, main() is entrypoint.

Call an exported function!

Page 10: A Recovering Java Developer Learns to Go

Why Go?

Page 11: A Recovering Java Developer Learns to Go

Iron Triangle of Language Design

Effic

ient

Com

pilat

ion

Ease of Programming

Efficient ExecutionSystems Programming

Page 12: A Recovering Java Developer Learns to Go

• 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

Page 13: A Recovering Java Developer Learns to Go

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.”

Page 14: A Recovering Java Developer Learns to Go

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.”

Page 15: A Recovering Java Developer Learns to Go

✓ Safety and efficiency of astatically-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

Page 16: A Recovering Java Developer Learns to Go

https://www.flickr.com/photos/slackpics/4289782818

Page 17: A Recovering Java Developer Learns to Go

A Kit for

Systems Software

https://www.flickr.com/photos/pmiaki/6657150957

Page 18: A Recovering Java Developer Learns to Go

Differences from Java

https://www.flickr.com/photos/yukop/6778321940

Page 19: A Recovering Java Developer Learns to Go

• Features and Idioms

• Packaging / Modularity

• Types / OOP / Interfaces

• Concurrency

Contrasts with Java

Page 20: A Recovering Java Developer Learns to Go

Features and

Idioms

https://www.flickr.com/photos/yukop/6778321940

Page 21: A Recovering Java Developer Learns to Go

Multiple Return Valuesfunc 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.

Page 22: A Recovering Java Developer Learns to Go

Closures

func intSeq() func() int { i := 0 return func() int { i += 1 return i } }

GBE

Closes over this state.

Page 23: A Recovering Java Developer Learns to Go

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.

Page 24: A Recovering Java Developer Learns to Go

Where’s my java.util.List? Slicess := 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!).

Page 25: A Recovering Java Developer Learns to Go

Where’s my java.util.List? Slicesc := 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!

Page 26: A Recovering Java Developer Learns to Go

Where’s my java.util.Map? Mapsm := 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

Page 27: A Recovering Java Developer Learns to Go

Where’s my java.util.Map? Mapsdelete(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

Page 28: A Recovering Java Developer Learns to Go

Looping with Rangenums := []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 -> %s\n", k, v) }

Discard first (index), sum second (value).

Keep both returns!

With maps, first = key, second = value.

GBE

Page 29: A Recovering Java Developer Learns to Go

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

Page 30: A Recovering Java Developer Learns to Go

(Semi)automatic Resource Managementfunc 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

Page 31: A Recovering Java Developer Learns to Go

(Semi)automatic Resource Management

func main() { f := createFile("/tmp/defer.txt") defer closeFile(f) writeFile(f) }

Run after the function completes.

GBE

Page 32: A Recovering Java Developer Learns to Go

Packaging/Modularity

https://www.flickr.com/photos/yukop/6778321940

Page 33: A Recovering Java Developer Learns to Go

TL;DR

COMPLEX

SIMPLE

Page 34: A Recovering Java Developer Learns to Go

• 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

Page 35: A Recovering Java Developer Learns to Go

• 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

Page 36: A Recovering Java Developer Learns to Go

• 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

Page 37: A Recovering Java Developer Learns to Go

• 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

Page 38: A Recovering Java Developer Learns to Go

• 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

Page 39: A Recovering Java Developer Learns to Go

• 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

Page 40: A Recovering Java Developer Learns to Go

• Java admits:

- circular package dependencies

- dead imports

• Go rejects:

- circular package dependencies

- dead imports

Miscellany

Page 41: A Recovering Java Developer Learns to Go

Types/OOP/Interfaces

https://www.flickr.com/photos/yukop/6778321940

Page 42: A Recovering Java Developer Learns to Go
Page 43: A Recovering Java Developer Learns to Go
Page 44: A Recovering Java Developer Learns to Go

For realz this time…

Page 45: A Recovering Java Developer Learns to Go

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!)

Page 46: A Recovering Java Developer Learns to Go

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.

Page 47: A Recovering Java Developer Learns to Go

composition FTWtype 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!

Page 48: A Recovering Java Developer Learns to Go

• 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

Page 49: A Recovering Java Developer Learns to Go
Page 50: A Recovering Java Developer Learns to Go

Interfaces Group Behaviors

type Positioner interface { Coordinates() Point } !type Distancer interface { DistanceTo(p Positioner) float64 }

Page 51: A Recovering Java Developer Learns to Go

It’s all about satisfaction…

Java = explicit !Go = implicit

Page 52: A Recovering Java Developer Learns to Go

Calculating Distancefunc 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) }

Page 53: A Recovering Java Developer Learns to Go

Point Satisfies Distancer and Positioner

func (p Point) Coordinates() Point { return p } !func (p Point) DistanceTo(pos Positioner) float64 { return distanceBetween(p, pos) }

Page 54: A Recovering Java Developer Learns to Go

ColorPoint Satisfies Distancer and Positioner

func (cp ColorPoint) Coordinates() Point { return cp.Point } !func (cp ColorPoint) DistanceTo(pos Positioner) float64 { return distanceBetween(cp, pos) }

Page 55: A Recovering Java Developer Learns to Go

Behavior Not Taxonomy

Page 56: A Recovering Java Developer Learns to Go

Animal Satisfies Distancer and Positionerfunc (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) }

Page 57: A Recovering Java Developer Learns to Go

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 = %v\n", p.DistanceTo(q)) fmt.Printf("Dist b/w q and p = %v\n", 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 = %v\n", penguin.DistanceTo(seal)) fmt.Printf("Dist b/w penguin and point = %v\n", penguin.DistanceTo(p))

Page 58: A Recovering Java Developer Learns to Go

Concurrency

https://www.flickr.com/photos/yukop/6778321940

Page 59: A Recovering Java Developer Learns to Go

• 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

Page 60: A Recovering Java Developer Learns to Go

• 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?

Page 61: A Recovering Java Developer Learns to Go

• Java - Shared memory - Locking

• Go - Can share memory (see http://golang.org/pkg/sync) - But there is a better way!

Synchronization?

Page 62: A Recovering Java Developer Learns to Go

– http://golang.org/doc/effective_go.html

“Do not communicate by sharing memory; instead, share memory by communicating.”

Page 63: A Recovering Java Developer Learns to Go

Goroutinesfunc 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

Page 64: A Recovering Java Developer Learns to Go

Channelsfunc main() { messages := make(chan string) ! go func() { messages <- "ping" }() ! msg := <-messages fmt.Println(msg) }

GBE

Create a new channel.

Sending

Receiving

Page 65: A Recovering Java Developer Learns to Go

Channel Bufferingfunc 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

Page 66: A Recovering Java Developer Learns to Go

Channel Synchronizationfunc 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!

Page 67: A Recovering Java Developer Learns to Go

Selectc1 := 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.

Page 68: A Recovering Java Developer Learns to Go

Selectfor 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!

Page 69: A Recovering Java Developer Learns to Go

Closing Channelsjobs := 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!

Page 70: A Recovering Java Developer Learns to Go

Closing Channelsfor 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.

Page 71: A Recovering Java Developer Learns to Go

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.

Page 72: A Recovering Java Developer Learns to Go

• Features and Idioms

• Packaging / Modularity

• Types / OOP / Interfaces

• Concurrency

Contrasts with Java

Page 73: A Recovering Java Developer Learns to Go

Thank You!!!Matt Stine (@mstine)

Cloud Foundry Platform Engineer at Pivotal [email protected]

http://www.mattstine.com

OFFICE HOURS Wednesday, 2:30 - 3:10 PM

Expo Hall (Table A)

Page 74: A Recovering Java Developer Learns to Go

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).


Top Related