go for rubyists

66
Go for Rubysts Thiago Pradi RubyConf Argentina - 2013

Upload: tchandy

Post on 06-May-2015

1.632 views

Category:

Technology


1 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Go for Rubyists

Go for RubystsThiago Pradi

RubyConf Argentina - 2013

Page 2: Go for Rubyists

whoami

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

Page 3: Go for Rubyists

Thiago was a happy Ruby developer...

Page 4: Go for Rubyists
Page 5: Go for Rubyists

that wanted to learn something new!

Page 6: Go for Rubyists

Why not a new language? ...

... Maybe Go!

Page 7: Go for Rubyists

Google trends - Golang

Page 8: Go for Rubyists

What is Go?

Page 9: Go for Rubyists

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

Page 10: Go for Rubyists

Go is an open source programming environment that makes it easy to build

simple, reliable, and efficient software.

Source: golang.org

Page 11: Go for Rubyists

Features

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

Page 12: Go for Rubyists

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

languages

Page 13: Go for Rubyists

Basic Concepts

Page 14: Go for Rubyists

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

Page 15: Go for Rubyists

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

Page 16: Go for Rubyists

Compiled language

Page 17: Go for Rubyists

Typesystem

Page 18: Go for Rubyists

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

Page 19: Go for Rubyists

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

Page 20: Go for Rubyists

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

Page 21: Go for Rubyists

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

Page 22: Go for Rubyists

Compiler

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

Page 23: Go for Rubyists

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

Page 24: Go for Rubyists

Organizing codepackage string_processing; func Process(str string) { // Code code code }

package mainimport "string_processing" func main() { string_processing.Process("foobar") }

Page 25: Go for Rubyists

Workspace

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

Page 26: Go for Rubyists
Page 27: Go for Rubyists

Encoding

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

Page 28: Go for Rubyists

Comparing it to Ruby..

Page 29: Go for Rubyists

Disclaimer

Page 30: Go for Rubyists

Object Orientation

• Ruby uses classes / methods • Golang uses Interfaces, adding methods to

data structures.

Page 31: Go for Rubyists

Objects in Ruby

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

Page 32: Go for Rubyists

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

a = Animal.new("Duck")a.say_something

Page 33: Go for Rubyists

Objects in Go

• No inheritance • Data types to define content • Methods define the operations • Interfaces define the behavior of the

“object” (data type)

Page 34: Go for Rubyists

package mainimport "fmt"type Animal struct { Name string }!

func (a *Animal) SaySomething() { fmt.Println("HEY HEY")}!

func main() { a := new(Animal) a.Name = "Duck" a.SaySomething()}

Page 35: Go for Rubyists

Error Handling

• Ruby uses Exceptions, with begin / rescue / ensure

• Golang use return values with error code (!!!)

Page 36: Go for Rubyists

Error handling - Ruby

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

Page 37: Go for Rubyists

file = File.open("/tmp/mel.txt", "w")!

begin # does some file processingrescue puts "Failed to process"ensure file.closeend

Page 38: Go for Rubyists

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

Page 39: Go for Rubyists

Off-topic: Gambiarra

Page 40: Go for Rubyists

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

Page 41: Go for Rubyists

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

Page 42: Go for Rubyists

func EchoFunction(connection net.Conn, ss *command_parser.ServerStorage) { defer connection.Close()!

buf := make([]byte, 1024) n, err := connection.Read(buf) // Heavy logic}

Page 43: Go for Rubyists

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")}

Page 44: Go for Rubyists

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")}

Page 45: Go for Rubyists

Concurrency

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

Page 46: Go for Rubyists

Concurrency - Ruby

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

Page 47: Go for Rubyists

require 'net/http'!

content = []!

thread = Thread.new do uri = URI("http://triremi.com/") content << Net::HTTP.get(uri)end!

thread.join

Page 48: Go for Rubyists

Concurrency - Go• Goroutines! • Lightweight thread implementation • Communications between goroutines using

channels • Managed by the Go Scheduler • Mapped to a few different OS processes

Page 49: Go for Rubyists

for { connection, err := listener.Accept()!

if err != nil { fmt.Println("Error accepting the socket") os.Exit(2) }!

EchoFunction(connection, ss) }

Page 50: Go for Rubyists

for { connection, err := listener.Accept()!

if err != nil { fmt.Println("Error accepting the socket") os.Exit(2) }!

go EchoFunction(connection, ss) }

Page 51: Go for Rubyists

import "fmt"!

func main() { messages := make(chan string)!

go PingFunction(messages)!

msg := <-messages!

fmt.Println(msg)}!

func PingFunction(messages chan string) { messages <- "ping"}

Page 52: Go for Rubyists

// Make the channel with the number of connectionschannels := make(chan ChannelResult, number_of_connections)!

// Start the request in a new goroutinego makeRequest(address, start_byte, end_byte, out, channels)!

//Wait for the result of the goroutine in the channelfor(loop_var < number_of_connections) { chan_res := <-channels // Process the result and save to the file}

Page 53: Go for Rubyists

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

Page 54: Go for Rubyists

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

Page 55: Go for Rubyists

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 endend

Page 56: Go for Rubyists

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

Page 57: Go for Rubyists

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") } }}

Page 58: Go for Rubyists

But, what about some real use cases?

Page 59: Go for Rubyists

Companies

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

Page 60: Go for Rubyists

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

Page 61: Go for Rubyists

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)

Page 62: Go for Rubyists

Wrapping up…• Cool language • Concurrent and networked • Benefits from both dynamic and static

languages • Modern • Give it a try!

Page 63: Go for Rubyists

One more thing..

Page 64: Go for Rubyists

GOLang!

Page 65: Go for Rubyists

GOLang!

Page 66: Go for Rubyists

Thank you!

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