Slide 1

Slide 1 text

Go for Rubysts Thiago Pradi RubyConf Argentina - 2013

Slide 2

Slide 2 text

whoami • Thiago Pradi • Brazilian! • Software Developer @ JobScore • Bachelor of Computer Science @ FURB • Octopus author / maintainer

Slide 3

Slide 3 text

Thiago was a happy Ruby developer...

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

that wanted to learn something new!

Slide 6

Slide 6 text

Why not a new language? ... ... Maybe Go!

Slide 7

Slide 7 text

Google trends - Golang

Slide 8

Slide 8 text

What is Go?

Slide 9

Slide 9 text

Go • Initially developed at Google • Created by Ken Thompson (Unix), Rob Pike (Plan 9), and Russ Cox (libtask) • Development started in 2007 • First release in 2009 (Fairly new!)

Slide 10

Slide 10 text

Go is an open source programming environment that makes it easy to build simple, reliable, and efficient software. Source: golang.org

Slide 11

Slide 11 text

Features • New • Concurrent • Compiled • Garbaged-collected • Simple & Fun!

Slide 12

Slide 12 text

Language focus • System programming • Networked / multi-core • Fast • Compatible with C • Best of static typed language and dynamic languages

Slide 13

Slide 13 text

Basic Concepts

Slide 14

Slide 14 text

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


Slide 15

Slide 15 text

C-Like Syntax func main() {
 fmt.Printf("Animal with name %s and age %d", "Anaconda", 32)
 }


Slide 16

Slide 16 text

Compiled language

Slide 17

Slide 17 text

Typesystem

Slide 18

Slide 18 text

Strong types func main() { var str string var value int str = "abc" value = 123 str + value }

Slide 19

Slide 19 text

Static Typed // types.go func main() {
 var a string
 
 a = 123
 }

Slide 20

Slide 20 text

with dynamic casting package main
 import ( "fmt" )
 
 func main() {
 a := 123
 fmt.Printf("Value of a: %d", a)
 }


Slide 21

Slide 21 text

User defined types package main;
 
 type Animal struct {
 Name string
 Age int
 }
 
 func main() {
 var anaconda Animal
 }


Slide 22

Slide 22 text

Compiler • Uses GCC as back end • Checks for unused packages and variables • Checks types and return values

Slide 23

Slide 23 text

Go tools • go fmt -> format your source code (cool!) • go get -> manage and install your dependencies • go build / run -> compile and run your program • go test -> run your tests

Slide 24

Slide 24 text

Organizing code package string_processing;
 
 func Process(str string) {
 // Code code code }
 package main 
 import "string_processing"
 func main() {
 string_processing.Process("foobar")
 }

Slide 25

Slide 25 text

Workspace • The default way to organize code in Go • Build to work with OpenSource repositories • Directories src, bin and pkg

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

Encoding • Source code: UTF-8 • Strings: UTF-8

Slide 28

Slide 28 text

Comparing it to Ruby..

Slide 29

Slide 29 text

Disclaimer

Slide 30

Slide 30 text

Object Orientation • Ruby uses classes / methods • Golang uses Interfaces, adding methods to data structures.

Slide 31

Slide 31 text

Objects in Ruby • Ruby Object model • Module / Class with methods • Support for inheritance and composition • Everything is an object

Slide 32

Slide 32 text

class Animal attr_accessor :name def initialize(name) self.name = name end def say_something puts "HEY HEY" end end ! a = Animal.new("Duck") a.say_something

Slide 33

Slide 33 text

Objects in Go • No inheritance • Data types to define content • Methods define the operations • Interfaces define the behavior of the “object” (data type)

Slide 34

Slide 34 text

package main import "fmt" type Animal struct { Name string } ! func (a *Animal) SaySomething() { fmt.Println("HEY HEY") } ! func main() { a := new(Animal) a.Name = "Duck" a.SaySomething() }

Slide 35

Slide 35 text

Error Handling • Ruby uses Exceptions, with begin / rescue / ensure • Golang use return values with error code (!!!)

Slide 36

Slide 36 text

Error handling - Ruby • Errors inherit from Exception class • Flow control with begin / rescue / ensure • Don’t need to treat every exception

Slide 37

Slide 37 text

file = File.open("/tmp/mel.txt", "w") ! begin # does some file processing rescue puts "Failed to process" ensure file.close end

Slide 38

Slide 38 text

Error Handling - Go • No exceptions • Errors should implement “Error” interface • Erros should be returned as additional value • Every error should be treated (unless you want to do a “Gambiarra”)

Slide 39

Slide 39 text

Off-topic: Gambiarra

Slide 40

Slide 40 text

func main() { fmt.Println("Starting MEL server") ! listener, err := net.Listen("tcp", "0.0.0.0:2653") ! if err != nil { fmt.Println("Error starting the server") os.Exit(1) } }

Slide 41

Slide 41 text

defer / panic / recover • Defer is compared to “ensure” in ruby • Panic / recover are similar to exception, but only should be used for internal APIs, never for external APIs. • Panic is used for runtime errors, like array out of bound

Slide 42

Slide 42 text

func EchoFunction(connection net.Conn, ss *command_parser.ServerStorage) { defer connection.Close() ! buf := make([]byte, 1024) n, err := connection.Read(buf) // Heavy logic }

Slide 43

Slide 43 text

func main() { PanicFunction() fmt.Println("This will not be printed") } ! func PanicFunction() { defer func() { fmt.Println("Called defer function") }() panic("PANIC PANIC PANIC") fmt.Println("This will not be printed") }

Slide 44

Slide 44 text

func main() { PanicFunction() fmt.Println("This will be printed") } ! func PanicFunction() { defer func() { if e := recover(); e != nil { fmt.Printf("Recovered from %s \n", e) } }() panic("PANIC PANIC PANIC") fmt.Println("This will not be printed") }

Slide 45

Slide 45 text

Concurrency • Ruby -> Threads / Fibers / EventPool / Actors • Go -> Goroutines

Slide 46

Slide 46 text

Concurrency - Ruby • Threads (with shared memory) • Fibers • EventMachine (Event loop / Reactor pattern) • Celluloid (Actor based)

Slide 47

Slide 47 text

require 'net/http' ! content = [] ! thread = Thread.new do uri = URI("http://triremi.com/") content << Net::HTTP.get(uri) end ! thread.join

Slide 48

Slide 48 text

Concurrency - Go • Goroutines! • Lightweight thread implementation • Communications between goroutines using channels • Managed by the Go Scheduler • Mapped to a few different OS processes

Slide 49

Slide 49 text

for { connection, err := listener.Accept() ! if err != nil { fmt.Println("Error accepting the socket") os.Exit(2) } ! EchoFunction(connection, ss) }

Slide 50

Slide 50 text

for { connection, err := listener.Accept() ! if err != nil { fmt.Println("Error accepting the socket") os.Exit(2) } ! go EchoFunction(connection, ss) }

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

// Make the channel with the number of connections channels := make(chan ChannelResult, number_of_connections) ! // Start the request in a new goroutine go makeRequest(address, start_byte, end_byte, out, channels) ! //Wait for the result of the goroutine in the channel for(loop_var < number_of_connections) { chan_res := <-channels // Process the result and save to the file }

Slide 53

Slide 53 text

Testing • Ruby has a built in framework (Test::Unit) and a lot of alternatives • Go also has a default framework for testing, and some early-stages alternatives

Slide 54

Slide 54 text

Testing in Ruby • Lots of frameworks: Test::Unit, rspec, MiniTest, Bacon… • Frameworks with lots of assertions and pre- defined macros • Easy to describe behavior (BDD) • Everyone tests.. (RIGHT?)

Slide 55

Slide 55 text

require "spec_helper" ! describe Octopus::Model do describe "#using method" do it "should return self" do User.using(:canada).should be_a(Octopus::ScopeProxy) end end end

Slide 56

Slide 56 text

Testing in Go • Light framework with the language, with a few new options • Don’t come with assertions / macros • Tests have the same package as the application code • Tests stay in the same directory of the application code

Slide 57

Slide 57 text

package command_parser; ! import ( “testing" ) ! func Test_parseSetCommand (t *testing.T) { ss := new(ServerStorage) ! str := ss.ParseCommand("SET thiagopradi valor") ! if ss.Dict["thiagopradi"] != "valor" { t.Error("failed to set thiagopradi key") } } }

Slide 58

Slide 58 text

But, what about some real use cases?

Slide 59

Slide 59 text

Companies • Google (dl.google.com, youtube) • SoundCloud • Heroku • CloudFlare • Ubuntu

Slide 60

Slide 60 text

Open Source • https://github.com/youtube/vitess - Process and tools for scaling MySQL • https://github.com/dotcloud/docker - Open Source application container engine • https://github.com/burke/zeus - Rails preloader

Slide 61

Slide 61 text

Mine • YADM - Yet another download manager (https://github.com/tchandy/yadm) • Brainfuck compiler (https://github.com/ tchandy/bf_compiler_go) • Mel - key-value database (https://github.com/ tchandy/mel)

Slide 62

Slide 62 text

Wrapping up… • Cool language • Concurrent and networked • Benefits from both dynamic and static languages • Modern • Give it a try!

Slide 63

Slide 63 text

One more thing..

Slide 64

Slide 64 text

GOLang!

Slide 65

Slide 65 text

GOLang!

Slide 66

Slide 66 text

Thank you! • www.thiagopradi.net • twitter.com/thiagopradi • [email protected]