diff --git a/2016/12-intro-to-golang/README.md b/2016/12-intro-to-golang/README.md new file mode 100644 index 0000000..719f863 --- /dev/null +++ b/2016/12-intro-to-golang/README.md @@ -0,0 +1,6 @@ +Usage +==== + + go get golang.org/x/tools/cmd/present + present . + diff --git a/2016/12-intro-to-golang/cats20.gif b/2016/12-intro-to-golang/cats20.gif new file mode 100644 index 0000000..b6c353a Binary files /dev/null and b/2016/12-intro-to-golang/cats20.gif differ diff --git a/2016/12-intro-to-golang/good0.go b/2016/12-intro-to-golang/good0.go new file mode 100644 index 0000000..3a3b880 --- /dev/null +++ b/2016/12-intro-to-golang/good0.go @@ -0,0 +1,48 @@ +// +build ignore + +package main + +import ( + "compress/gzip" + "encoding/json" + "flag" + "io/ioutil" + "log" + "os" +) + +func main() { + for _, arg := range flag.Args() { + func() { + // START1 OMIT + fh, err := os.Open(arg) + if err != nil { + log.Fatal(err) + } + defer fh.Close() + + gz, err := gzip.NewReader(fh) + if err != nil { + log.Fatal(err) + } + defer gz.Close() + + buf, err := ioutil.ReadAll(gz) + if err != nil { + log.Fatal(err) + } + + var mine MyStruct + err = json.Unmarshal(&mine) + if err != nil { + log.Fatal(err) + } + // STOP1 OMIT + + }() + } + +} + +type MyStruct struct { +} diff --git a/2016/12-intro-to-golang/good1.go b/2016/12-intro-to-golang/good1.go new file mode 100644 index 0000000..84a3b6e --- /dev/null +++ b/2016/12-intro-to-golang/good1.go @@ -0,0 +1,20 @@ +// +build ignore + +package main + +// START1 OMIT +// exported +type Foo struct { + Bar string // exported + baz bool // private +} + +// private +type bif struct { + Harf, Buz int64 // doesn't matter +} + +// STOP1 OMIT + +func main() { +} diff --git a/2016/12-intro-to-golang/gopher.png b/2016/12-intro-to-golang/gopher.png new file mode 100644 index 0000000..cb5e2e1 Binary files /dev/null and b/2016/12-intro-to-golang/gopher.png differ diff --git a/2016/12-intro-to-golang/hello.go b/2016/12-intro-to-golang/hello.go new file mode 100644 index 0000000..8ad6d97 --- /dev/null +++ b/2016/12-intro-to-golang/hello.go @@ -0,0 +1,10 @@ +// +build ignore + +// START1 OMIT +package main + +func main() { + println("Howdy y'all") +} + +// STOP1 OMIT diff --git a/2016/12-intro-to-golang/imports.go b/2016/12-intro-to-golang/imports.go new file mode 100644 index 0000000..ba18875 --- /dev/null +++ b/2016/12-intro-to-golang/imports.go @@ -0,0 +1,18 @@ +// +build ignore + +package main + +// START1 OMIT +import ( + "fmt" + "os" + + "github.com/foo/bar" +) + +// STOP1 OMIT + +func main() { + fmt.Println(bar.Baz()) + _ = os.FileInfo +} diff --git a/2016/12-intro-to-golang/kanye_imma_bookmarklet.png b/2016/12-intro-to-golang/kanye_imma_bookmarklet.png new file mode 100644 index 0000000..e896826 Binary files /dev/null and b/2016/12-intro-to-golang/kanye_imma_bookmarklet.png differ diff --git a/2016/12-intro-to-golang/pingpong.go b/2016/12-intro-to-golang/pingpong.go new file mode 100644 index 0000000..159d2c5 --- /dev/null +++ b/2016/12-intro-to-golang/pingpong.go @@ -0,0 +1,33 @@ +// +build OMIT + +package main + +import ( + "fmt" + "time" +) + +// STARTMAIN1 OMIT +type Ball struct{ hits int } + +func main() { + table := make(chan *Ball) + go player("ping", table) + go player("pong", table) + + table <- new(Ball) // game on; toss the ball + time.Sleep(1 * time.Second) + <-table // game over; grab the ball +} + +func player(name string, table chan *Ball) { + for { + ball := <-table + ball.hits++ + fmt.Println(name, ball.hits) + time.Sleep(100 * time.Millisecond) + table <- ball + } +} + +// STOPMAIN1 OMIT diff --git a/2016/12-intro-to-golang/primitive1.go b/2016/12-intro-to-golang/primitive1.go new file mode 100644 index 0000000..d9e1961 --- /dev/null +++ b/2016/12-intro-to-golang/primitive1.go @@ -0,0 +1,25 @@ +// +build ignore + +package main + +import "fmt" + +func main() { + // START1 OMIT + names := []string{ + "Michael", + "Jan", + "Sean", + "Silvia", + } + for i, name := range names { + fmt.Printf("%q is the %d name\n", name, i) + } + for i := range names { + fmt.Printf("%q is the %d name\n", names[i], i) + } + for _, name := range names { + fmt.Printf("%q is the ... name\n", name) + } + // STOP1 OMIT +} diff --git a/2016/12-intro-to-golang/primitive2.go b/2016/12-intro-to-golang/primitive2.go new file mode 100644 index 0000000..9d54624 --- /dev/null +++ b/2016/12-intro-to-golang/primitive2.go @@ -0,0 +1,56 @@ +// +build ignore + +package main + +import "fmt" + +func main() { + // START1 OMIT + infos := map[string]Info{ + "Michael": Info{ + City: "Happyville", + Status: Open, + }, + "Jan": Info{ + City: "Confusville", + Status: Closed, + }, + "Sean": Info{ + City: "Septober", + Status: Complicated, + }, + "Silvia": Info{ + City: "Curiousville", + Status: Curios, + }, + } + for name, info := range infos { + fmt.Printf("%q is %s in %q\n", name, info.Status, info.City) + } + // STOP1 OMIT +} + +type Info struct { + City string + Status Status +} +type Status int + +var ( + Open = Status(0) + Closed = Status(1) + Complicated = Status(2) + Curios = Status(3) +) + +func (s Status) String() string { + switch s { + case Open: + return "open" + case Closed: + return "closed" + case Complicated: + return "complicated" + } + return "hurr" +} diff --git a/2016/12-intro-to-golang/primitive3.go b/2016/12-intro-to-golang/primitive3.go new file mode 100644 index 0000000..c3329d5 --- /dev/null +++ b/2016/12-intro-to-golang/primitive3.go @@ -0,0 +1,37 @@ +// +build ignore + +package main + +import "fmt" + +func main() { + // START1 OMIT + fmt.Println("I've got:") + for card := range ReadEmAndWeep() { + fmt.Printf(" %s of %s\n", card.Value, card.Suite) + } + // STOP1 OMIT +} + +type Card struct { + Suite, Value string +} + +// START2 OMIT +func ReadEmAndWeep() <-chan Card { + c := make(chan Card) + go func() { + for _, card := range []Card{ + Card{"Ace", "Jack"}, + Card{"Ace", "Queen"}, + Card{"Ace", "King"}, + Card{"Ace", "Ace"}, + } { + c <- card + } + close(c) + }() + return c +} + +// STOP2 OMIT diff --git a/2016/12-intro-to-golang/rainbow.jpg b/2016/12-intro-to-golang/rainbow.jpg new file mode 100644 index 0000000..eb3c98e Binary files /dev/null and b/2016/12-intro-to-golang/rainbow.jpg differ diff --git a/2016/12-intro-to-golang/revenge-of-the-nerds-o.gif b/2016/12-intro-to-golang/revenge-of-the-nerds-o.gif new file mode 100644 index 0000000..fce49b6 Binary files /dev/null and b/2016/12-intro-to-golang/revenge-of-the-nerds-o.gif differ diff --git a/2016/12-intro-to-golang/tags.go b/2016/12-intro-to-golang/tags.go new file mode 100644 index 0000000..6e89e71 --- /dev/null +++ b/2016/12-intro-to-golang/tags.go @@ -0,0 +1,8 @@ +// START1 OMIT +// +build !windows linux,cgo +// STOP1 OMIT + +package main + +func main() { +} diff --git a/2016/12-intro-to-golang/talk.slide b/2016/12-intro-to-golang/talk.slide new file mode 100644 index 0000000..0d819a7 --- /dev/null +++ b/2016/12-intro-to-golang/talk.slide @@ -0,0 +1,214 @@ +Intro to Golang +05 December 2016 + +Vincent Batts +Developer +@vbatts +vbatts@redhat.com +https://github.com/vbatts/talks + +* howdy + + $> finger $(whoami) + Login: vbatts Name: Vincent Batts + Such mail. + Plan: + right and joyful effort + $> id -Gn + vbatts devel redhat oci openshift slackware docker + + +* golang + +## Notes +# - libraries - source only, but can link to C *.so and *.a +# - Fork/Exec are coupled together (for coroutine and GC reasons) +# - Threading, and multiproc, concurrent logic +# -- nice and easy to use +# -- Make for tricky handling of C calls (i.e. setns) +# - `go get` is handy +# - cross-compile without hardly any bootstrapping +# -- native compiler supported arches +# -- gccgo works for the arch gcc is compiled for +# - primitives can seem a bit magical +# -- conditional returns +# -- for ... range +# -- iota +# - no ifdefs, but build tags +# - error handling, rather than exception catching + + +* + +.image ./gopher.png + + +* Overview + +- strongly typed +- compiled +- stylistically nice +- opinionated/idiomatic + + +* + +.image ./rainbow.jpg + + +* fully qualified imports + +.code ./imports.go /START1/,/STOP1/ + + +* fast compiles + +(Perhaps other compilers are slow) + +.play ./hello.go /START1/,/STOP1/ + + +* defer + +.code ./good0.go /START1/,/STOP1/ + + +* Garbage Collected + +- Super convenient +- references +- completed goroutines + + +* Garbage Collected + +.link https://twitter.com/brianhatfield/status/634166123605331968 Brian Hatfield GC improvements + +- go1.4 (300ms) -> go1.5 (~30ms) +- go1.6.0 (25ms) -> go1.6.3 (5ms) +- go1.7.3 (3ms) -> go1.8beta1 (sub ms on 18Gb heap) + + +* simple exports + +.code ./good1.go /START1/,/STOP1/ + + +* concurrency + +.play ./pingpong.go /STARTMAIN1/,/STOPMAIN1/ +.link http://talks.golang.org/2013/advconc.slide Sameer Ajmani - Advanced Concurrency + + +* +.image ./kanye_imma_bookmarklet.png 320 _ + +- easy learning curve +- `go get` +- cross-compiles + + +* + +# they come along, and affect how you do your work +.image ./cats20.gif + + +* Packaging + +Addresses different concern than distributions + +* lack of generics? +# i don't feel strongly about this, though many do +- interfaces - are enough for most +- go1.4 introduced go:generate +# produce code for Set, Graph etc, for the types needed, but at compile time. No need to reflect. + + +* Debugging + +- gdb is there, sort of +- some known debugging tools for ELF are not useful +- fmt.Printf("%#v\n", ...) + + +* Concurrency and CGO + +Calls like setns(2) are rough + +(yes, even with runtime.LockOSThread()) + +Embedding other languages (like ruby and python that have their green threading) + + +* Fork/Exec + +Not Separate, but together + + +* +.image ./revenge-of-the-nerds-o.gif + + +* build tags + +no #ifdef + +.code ./tags.go /START1/,/STOP1/ + +or files with *_linux.go like suffix. + +More like extern. + + +* _ + +bit bucket + + +* channels + +.play ./ugly0.go /START1/,/STOP1/ + + +* iota + +.code ./ugly1.go /START1/,/STOP1/ + + +* for range + +array (or string) + +.play ./primitive1.go /START1/,/STOP1/ + + +* for range + +map + +.play ./primitive2.go /START1/,/STOP1/ + + +* for range + +channel (like an iterator) + +.play ./primitive3.go /START1/,/STOP1/ + + +* for range + +channel + +.code ./primitive3.go /START2/,/STOP2/ + + +* Conclusions? + + +* use-case + +- like all languages, align with you use-case +- get familiar enough to like and dislike it +- don't be afraid to try it out diff --git a/2016/12-intro-to-golang/ugly0.go b/2016/12-intro-to-golang/ugly0.go new file mode 100644 index 0000000..715c384 --- /dev/null +++ b/2016/12-intro-to-golang/ugly0.go @@ -0,0 +1,16 @@ +// +build ignore + +package main + +func main() { + // START1 OMIT + c := make(chan int) + go func() { + for i := 0; i < 10; i++ { + c <- i + } + close(c) + }() + println(<-c) + // STOP1 OMIT +} diff --git a/2016/12-intro-to-golang/ugly1.go b/2016/12-intro-to-golang/ugly1.go new file mode 100644 index 0000000..3d72e71 --- /dev/null +++ b/2016/12-intro-to-golang/ugly1.go @@ -0,0 +1,22 @@ +// +build ignore + +package main + +// START1 OMIT +const ( + DeviceCreate TaskType = iota + DeviceReload + DeviceRemove + DeviceRemoveAll + DeviceSuspend + DeviceResume + DeviceInfo + DeviceDeps +) + +// STOP1 OMIT + +type TaskType int + +func main() { +}