GO FOR RUBYISTS?
Luka Zakrajšek
CTO @ Koofr
@bancek
Slovenia Ruby User Group, January Meetup
January 29, 2015
ABOUT MEFRI graduateCTO and cofounder at Koofr
Python developer in previous lifenow mostly Scala, Go and JavaScript
GO @ KOOFRKoofr is white-label cloud storage solution for ISPs
backendcontent server (downloads, uploads, streaming ...)FTP server...
desktop applicationGUI applicationsyncremote filesystem access
WHAT IS GOnew programming language from Googlelow levelC-like syntaxfast compilation (for large codebases)compiles to single binarycross platform (Windows, Linux, Mac)
WHAT IS GOstatically-typedmanaged memory (garbage collection)type safetydynamic-typing capabilitiesbuilt-in types (variable-length arrays and key-value maps)large standard library
GO IS C#include <stdio.h> main(){ printf("Hello World\n"); return 0;}
package main
import "fmt"
func main() { fmt.Println("Hello World")}
GO IS PYTHONimport reimport osimport Imageimport csvimport jsonimport gzipimport urllibimport unittest
import ( "regexp" "os.exec" "image/jpeg" "encoding/csv" "encoding/json" "compress/gzip" "net/http" "testing")
import "github.com/koofr/go-koofrclient"
GO IS NODE.JSvar http = require('http');http.createServer(function (req, res) { res.writeHead(200); res.end('Hello World');}).listen(1337, '127.0.0.1');console.log('Server running at http://127.0.0.1:1337/');
package mainimport ( "fmt" "net/http")func main() { http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") }) http.ListenAndServe(":1337", nil) fmt.Println("Server running at http://127.0.0.1:1337/");}
EASY AND CHEAP CONCURRENCYeasy to have dozens (or even thousands) of concurrentoperations
it will even take advantage of all the CPUs available
Ruby has threads, but there is GIL in Ruby MRI
Ruby has green threads, but will use single CPU
LOW MEMORY OVERHEADGo programs can be compiled to a few megabytes binary
memory efficient while harvesting the power of the entiremachine
EASY DEPLOYMENTGo programs are compiled in a few seconds into smallexecutables
no dependencies in production
USE GO FROM RUBYGo:
package main import "fmt"import "encoding/json" func main() { mapD := map[string]int{"apple": 5, "lettuce": 7} mapB, _ := json.Marshal(mapD) fmt.Println(string(mapB))}
Ruby:JSON.parse(go run json.go)# => {"apple"=>5, "lettuce"=>7}
https://antoine.finkelstein.fr/go-in-ruby/
IMPORTSlocal imports (GOPATH env. variable)import directly from web (http, git, mercurial)capitalized identifiers are exported
import ( "fmt" "github.com/koofr/go-koofrclient")
FUNCTIONStake zero or more argumentsa function can return any number of results.types come after variable namesnamed return values
func myfunction(x, y int) (x int, y int) { tmp := x x = y y = tmp return // return y, x}
VARIABLESvar statement declares a list of variablestype comes after name
var c, python, java bool
func main() { var i int fmt.Println(i, c, python, java)}
short variable declarations
func main() { var i int = 1 k := 3 // type inference}
BASIC TYPESboolstringint, uint, int8, uint, int16, uint16, int32, uint32, int64, uint64,uintptrbyte // alias for uint8rune // alias for int32, represents a Unicode code pointfloat32, float64complex64, complex128
INTERFACEStype SizeReader struct { r io.Reader size int64}func (sr *SizeReader) Read(p []byte) (n int, err error) { n, err = sr.r.Read(p) sr.size += int64(n) return}func consumeReader(r io.Reader) { // ...}func main() { var sr *SizeReader = &SizeReader{myFile, 0} consumeReader(sr) fmt.Println(sr.size)}
GOROUTINES AND CHANNELSfunc doSomethingExpensive() int { time.Sleep(10 * time.Second) return 42}
func doItAsync() { go doSomethingExpensive()}
func doItAsyncAndGetResult() <-chan int { ch := make(chan int, 1) go func() { ch <- doSomethingExpensive() }() return ch}
ERROR HANDLINGfunc copyFile(src string, dest string) (i64, error) { r, err := os.Open(src) if err != nil { return err } defer r.Close()
w, err := os.Create(dest) if err != nil { return err } defer w.Close()
bytesCopied, err = io.Copy(w, r)
return bytesCopied, err}
GO COMMAND// fetch dependenciesgo get
// run testsgo test
// build binarygo build
// format codego fmt
// check for errors in codego vet
APPLICATION STRUCTUREsrc/ github.com/ koofr/ go-ioutils myapp/ internallib/ lib.go main/ main.go config.go myapp.go
bin/ myapppkg/build/dist/
TESTINGpackage newmath
import "testing"
func TestSqrt(t *testing.T) { const in, out = 4, 2 if x := Sqrt(in); x != out { t.Errorf("Sqrt(%v) = %v, want %v", in, x, out) }}
$ go testok github.com/user/newmath 0.165s
DEPLOYMENTgo build -o bin/myapp src/myapp/main/main.go
scp bin/myapp myserver.com:myapp
ssh myserver.com 'supervisorctl restart myapp'
FEATURESFlexible RoutingVery flexible and extremely DRY. Name parameters, stack handlers,inject the dependencies.
ComprehensiveComes with a great set of stock middleware:Logging, Recovery, Static file serving, Authentication, Routing and more!
Reuse Existing CodeFully compatible with Go's http.HandlerFunc interface.Leverage the many awesome open source web packages built in Go
MARTINI EXAMPLEpackage main
import "github.com/go-martini/martini"
func main() { m := martini.Classic()
m.Get("/", func() string { return "Hello world!" })
m.Get("/hello/:name", func(params martini.Params) string { return "Hello " + params["name"] })
m.Run()}
FEATURESHot Code ReloadEdit, save, and refresh.
Comprehensiverouting, parameter parsing, validation, session/flash,templating, caching, job running, a testing framework, internationalization ...
High PerformanceBuilt on top of the Go HTTP server, three to ten times as many requests as Rails
FRAMEWORK DESIGNSynchronousThe Go HTTP server runs each request in its own goroutine.Write simple callback-free code without guilt.
StatelessProvides primitives that keep the web tier stateless for predictable scaling.Session data in stored cookies, cache backed by a memcached cluster.
ModularComposable middleware called filters, which implement nearly allrequest-processing functionality
REVEL PROJECT STRUCTURE myapp App root app App sources controllers App controllers init.go Interceptor registration models App domain models routes Reverse routes (generated code) views Templates tests Test suites conf Configuration files app.conf Main configuration file routes Routes definition messages Message files public Public assets css CSS files js Javascript files images Image files