go for rubyists

Post on 06-May-2015

1.633 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

Go for RubystsThiago Pradi

RubyConf Argentina - 2013

whoami

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

Thiago was a happy Ruby developer...

that wanted to learn something new!

Why not a new language? ...

... Maybe Go!

Google trends - Golang

What is Go?

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

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

simple, reliable, and efficient software.

Source: golang.org

Features

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

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

languages

Basic Concepts

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

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

Compiled language

Typesystem

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

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

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

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

Compiler

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

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

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

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

Workspace

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

Encoding

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

Comparing it to Ruby..

Disclaimer

Object Orientation

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

data structures.

Objects in Ruby

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

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

Objects in Go

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

“object” (data type)

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

Error Handling

• Ruby uses Exceptions, with begin / rescue / ensure

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

Error handling - Ruby

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

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

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

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

Off-topic: Gambiarra

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

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

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

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

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

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

Concurrency

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

Concurrency - Ruby

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

require 'net/http'!

content = []!

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

thread.join

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

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

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

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

EchoFunction(connection, ss) }

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

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

go EchoFunction(connection, ss) }

import "fmt"!

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

go PingFunction(messages)!

msg := <-messages!

fmt.Println(msg)}!

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

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

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

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

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

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

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

But, what about some real use cases?

Companies

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

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

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)

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

languages • Modern • Give it a try!

One more thing..

GOLang!

GOLang!

Thank you!

• www.thiagopradi.net • twitter.com/thiagopradi • thiago.pradi@gmail.com

top related