Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go for Rubysts

thiagopradi
November 27, 2013

Go for Rubysts

This presentation tries to introduce people that are familiar to ruby with Go.

thiagopradi

November 27, 2013
Tweet

More Decks by thiagopradi

Other Decks in Technology

Transcript

  1. whoami • Thiago Pradi • Brazilian! • Software Developer @

    JobScore • Bachelor of Computer Science @ FURB • Octopus author / maintainer
  2. 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!)
  3. Go is an open source programming environment that makes it

    easy to build simple, reliable, and efficient software. Source: golang.org
  4. Language focus • System programming • Networked / multi-core •

    Fast • Compatible with C • Best of static typed language and dynamic languages
  5. Strong types func main() { var str string var value

    int str = "abc" value = 123 str + value }
  6. with dynamic casting package main
 import ( "fmt" )
 


    func main() {
 a := 123
 fmt.Printf("Value of a: %d", a)
 }

  7. User defined types package main;
 
 type Animal struct {


    Name string
 Age int
 }
 
 func main() {
 var anaconda Animal
 }

  8. Compiler • Uses GCC as back end • Checks for

    unused packages and variables • Checks types and return values
  9. 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
  10. Organizing code package string_processing;
 
 func Process(str string) {
 //

    Code code code }
 package main 
 import "string_processing"
 func main() {
 string_processing.Process("foobar")
 }
  11. Workspace • The default way to organize code in Go

    • Build to work with OpenSource repositories • Directories src, bin and pkg
  12. Object Orientation • Ruby uses classes / methods • Golang

    uses Interfaces, adding methods to data structures.
  13. Objects in Ruby • Ruby Object model • Module /

    Class with methods • Support for inheritance and composition • Everything is an object
  14. 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
  15. Objects in Go • No inheritance • Data types to

    define content • Methods define the operations • Interfaces define the behavior of the “object” (data type)
  16. 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() }
  17. Error Handling • Ruby uses Exceptions, with begin / rescue

    / ensure • Golang use return values with error code (!!!)
  18. Error handling - Ruby • Errors inherit from Exception class

    • Flow control with begin / rescue / ensure • Don’t need to treat every exception
  19. file = File.open("/tmp/mel.txt", "w") ! begin # does some file

    processing rescue puts "Failed to process" ensure file.close end
  20. 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”)
  21. 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) } }
  22. 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
  23. func EchoFunction(connection net.Conn, ss *command_parser.ServerStorage) { defer connection.Close() ! buf

    := make([]byte, 1024) n, err := connection.Read(buf) // Heavy logic }
  24. 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") }
  25. 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") }
  26. Concurrency - Ruby • Threads (with shared memory) • Fibers

    • EventMachine (Event loop / Reactor pattern) • Celluloid (Actor based)
  27. require 'net/http' ! content = [] ! thread = Thread.new

    do uri = URI("http://triremi.com/") content << Net::HTTP.get(uri) end ! thread.join
  28. Concurrency - Go • Goroutines! • Lightweight thread implementation •

    Communications between goroutines using channels • Managed by the Go Scheduler • Mapped to a few different OS processes
  29. for { connection, err := listener.Accept() ! if err !=

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

    nil { fmt.Println("Error accepting the socket") os.Exit(2) } ! go EchoFunction(connection, ss) }
  31. import "fmt" ! func main() { messages := make(chan string)

    ! go PingFunction(messages) ! msg := <-messages ! fmt.Println(msg) } ! func PingFunction(messages chan string) { messages <- "ping" }
  32. // 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 }
  33. 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
  34. 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?)
  35. 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
  36. 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
  37. 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") } } }
  38. 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
  39. 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)
  40. Wrapping up… • Cool language • Concurrent and networked •

    Benefits from both dynamic and static languages • Modern • Give it a try!