Your SlideShare is downloading. ×
0
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Go: It's Not Just For Google
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Go: It's Not Just For Google

6,876

Published on

Another slab of Google Go madness with an emphasis on code and reflection.

Another slab of Google Go madness with an emphasis on code and reflection.

Published in: Technology, Business
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,876
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
106
Comments
0
Likes
12
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    • 1. Ro u gh Cut !Goit’s not just for GoogleEleanor McHughhttp://slides.games-with-brains.net/
    • 2. compiled
    • 3. garbage collected
    • 4. imperative
    • 5. package mainimport “fmt”const HELLO string = “hello”var WORLD string = “world”func main() { fmt.Println(HELLO, WORLD)}
    • 6. strongly typed
    • 7. boolean, numeric, array value structure, interfacereference pointer, slice, string, map, channelfunction function, method, closure
    • 8. underlying method type set expressed type
    • 9. underlying method type set expressed type embedded types
    • 10. package Integertype Int intfunc (i *Int) Add(x int) { *i += Int(x)}
    • 11. type Buffer []Intfunc (b Buffer) Swap(i, j int) { b[i], b[j] = b[j], b[i]}func (b Buffer) Clone() Buffer { s := make(Buffer, len(b)) copy(s, b) return s}func (b Buffer) Move(i, n int) { if n > len(b) - i { n = len(b) - i } segment_to_move := b[:i].Clone() copy(b, b[i:i + n]) copy(b[n:i + n], segment_to_move)}
    • 12. package mainimport “fmt”import "Integer"func main() { i := Integer.Buffer{0, 1, 2, 3, 4, 5} produces: b := i.Clone() b[0:2] = [6 4] b.Swap(1, 2) b.Move(3, 2) b[0].Add(3) fmt.Printf(“b[0:2] = %vn”, b[0:2])}
    • 13. testable
    • 14. func (b Buffer) Eq(o Buffer) (r bool) { if len(b) == len(o) { for i := len(b) - 1; i > 0; i-- { if b[i] != o[i] { return } } r = true } return}
    • 15. func TestSwap(t *testing.T) { i := Buffer{0, 1, 2, 3, 4, 5} b := i.Clone() b.Swap(1, 2) if !b[1:3].Eq(Buffer{2, 1}) { t.Fatalf("b = %v", b) }}
    • 16. package Vectorimport . "Integer"type Vector struct { Buffer}func (v *Vector) Clone() *Vector { return &Vector{v.Buffer.Clone()}}func (v *Vector) Slice(i, j int) Buffer { return v.Buffer[i:j]}
    • 17. package Vectorimport "testing"func TestVectorSwap(t *testing.T) { i := Vector{Buffer{0, 1, 2, 3, 4, 5}} v := i.Clone() v.Swap(1, 2) r := Vector{Buffer{0, 2, 1, 3, 4, 5}} switch { case !v.Eq(r.Buffer): fallthrough case !v.Buffer.Eq(r.Buffer): t.Fatalf("b[0:5] = %v", v) }}
    • 18. include $(GOROOT)/src/Make.incTARG=integerGOFILES= integer.go vector.goinclude $(GOROOT)/src/Make.pkg
    • 19. func BenchmarkVectorClone6(b *testing.B) { v := Vector{Buffer{0, 1, 2, 3, 4, 5}} for i := 0; i < b.N; i++ { _ = v.Clone() }}func BenchmarkVectorSwap(b *testing.B) { b.StopTimer() v := Vector{Buffer{0, 1, 2, 3, 4, 5}} b.StartTimer() for i := 0; i < b.N; i++ { v.Swap(1, 2) }}
    • 20. $ gotest -bench="Benchmark"rm -f _test/scripts.a6g -o _gotest_.6 integer.go vector.go nominal_typing_test.goembedded_typing_benchmark_test.go embedded_typing_test.gorm -f _test/scripts.agopack grc _test/scripts.a _gotest_.6PASSinteger.BenchmarkVectorSwap 200000000 8 ns/opinteger.BenchmarkVectorClone6 10000000 300 ns/op
    • 21. dynamic
    • 22. type Adder interface { Add(j int) Subtract(j int) Result() interface{} Reset()}
    • 23. type IAdder intfunc (i IAdder) Add(j int) { i[0] += i[j]}func (i IAdder) Subtract(j int) { i[0] -= i[j]}func (i IAdder) Result() interface{} { return i[0]}func (i IAdder) Reset() { i[0] = *new(int)}
    • 24. type FAdder []float32func (f FAdder) Add(j int) { f[0] += f[j]}func (f FAdder) Subtract(j int) { f[0] -= f[j]}func (f FAdder) Result() interface{} { return f[0]}
    • 25. func TestAdder(t *testing.T) { var a Adder a = IAdder{0, 1, 2} a.Add(1) if i.Result().(int) != 1 { t.Fatalf("IAdder::Add(1) %v != %v", a.Result(), 1) } a.Subtract(2) if a.Result().(int) != -1 { t.Fatalf("IAdder::Subtract(2) %v != %v", a.Result()), -1 } a = FAdder{0.0, 1.0, 2.0} a.Add(1) if a.Result().(float32) != 1.0 { t.Fatalf("FAdder::Add(1) %v != %v", a.Result(), 1.0) }}
    • 26. reflected
    • 27. package generaliseimport "reflect"func Allocate(i interface{}, limit... int) (n interface{}) { switch v := reflect.ValueOf(i); v.Kind() { case reflect.Slice: l := v.Cap() if len(limit) > 0 { l = limit[0] } n = reflect.MakeSlice(v.Type(), l, l).Interface() case reflect.Map: n = reflect.MakeMap(v.Type()).Interface() } return}
    • 28. package generaliseimport . "reflect"func Allocate(i interface{}, limit... int) (n interface{}) { switch v := ValueOf(i); v.Kind() { case Slice: l := v.Cap() if len(limit) > 0 { l = limit[0] } n = MakeSlice(v.Type(), l, l).Interface() case Map: n = MakeMap(v.Type()).Interface() } return}
    • 29. func throwsPanic(f func()) (b bool) { defer func() { if x := recover(); x != nil { b = true } }() f() return}
    • 30. func TestAllocate(t *testing.T) { var s2 []int s1 := []int{0, 1, 2} m := map[int] int{1: 1, 2: 2, 3: 3} switch { case throwsPanic(func() { s2 = Allocate(s1, 1).([]int) }): t.Fatal("Unable to allocate new slice") case len(s2) != 1 || cap(s2) != 1: t.Fatal("New slice should be %v not %v", make([]int, 0, 1), s2) case throwsPanic(func() { Allocate(m) }): t.Fatal("Unable to allocate new map") }}
    • 31. func Duplicate(i interface{}) (clone interface{}) { if clone = Allocate(i); clone != nil { switch clone := ValueOf(clone); clone.Kind() { case Slice: Copy(clone, ValueOf(i)) case Map: m := ValueOf(i) for _, k := range m.Keys() { clone.SetMapIndex(k, m.MapIndex(k)) } } } return}
    • 32. func TestDuplicateSlice(t *testing.T) { s1 := []int{0, 1, 2} var s2 []int if throwsPanic(func() { s2 = Duplicate(s1).([]int) }) { t.Fatalf("Unable to duplicate slice %vn", s1) } switch { case len(s1) != len(s2): fallthrough case cap(s1) != cap(s2): fallthrough case s1[0] != s2[0]: fallthrough case s1[1] != s2[1]: fallthrough case s1[2] != s2[2]: fallthrough t.Fatalf("Duplicating %v produced %v", s1, s2) }}
    • 33. func TestDuplicateMap(t *testing.T) { m1 := map[int]int{1: 1, 2: 2, 3: 3} var m2 map[int]int if throwsPanic(func() { m2 = Duplicate(m1).(map[int]int) }) { t.Fatalf("Unable to duplicate map %vn", m1) } switch { case len(m1) != len(m2): fallthrough case m1[1] != m2[1]: fallthrough case m1[2] != m2[2]: fallthrough case m1[3] != m2[3]: fallthrough t.Fatalf("Duplicating %v produced %v", m1, m2) }}
    • 34. low-level
    • 35. package rawimport . "reflect"import "unsafe"var _BYTE_SLICE Type = Typeof([]byte(nil))type MemoryBlock interface { ByteSlice() []byte}func valueHeader(v reflect.Value) (Header *reflect.SliceHeader) { if v.IsValid() { s := int(v.Type().Size()) header = &reflect.SliceHeader{ v.UnsafeAddr(), s, s } } return}
    • 36. func SliceHeader(i interface{}) (Header *SliceHeader, Size, Align int) { switch value := Indirect(ValueOf(i)); value.Kind() { case Slice: Header = (*SliceHeader)(unsafe.Pointer(value.UnsafeAddr())) t := value.Type().Elem() Size = int(t.Size()) Align = t.Align() case Interface: Header, Size, Align = SliceHeader(value.Elem()) } return}func Scale(oldHeader *SliceHeader, oldESize, newESize int) (h *SliceHeader) { if oldHeader != nil { s := float64(oldESize) / float64(newESize) h = &SliceHeader{ Data: oldHeader.Data } h.Len = int(float64(oldHeader.Len) * s) h.Cap = int(float64(oldHeader.Cap) * s) } return}
    • 37. func ByteSlice(i interface{}) []byte { switch i := i.(type) { case []byte: return i case MemoryBlock: return i.ByteSlice() } var header *SliceHeader switch v := ValueOf(i); value.Kind() { case Interface, Ptr: header = valueHeader(v.Elem()) case Slice: h, s, _ := SliceHeader(i) header = Scale(h, s, 1) case String: s := v.Get() h := *(*StringHeader)(unsafe.Pointer(&s)) header = &SliceHeader{ h.Data, h.Len, h.Len } default: header = valueHeader(v) } return unsafe.Unreflect(_BYTE_SLICE, unsafe.Pointer(header)).([]byte)}
    • 38. concurrent
    • 39. package mainimport "fmt"func main() { var c chan int c = make(chan int) limit := 16 go func() { for i := limit; i > 0; i-- { produces: fmt.Print(<-c) 0110011101011010 } }() for i := limit; i > 0; i-- { select { case c <- 0: case c <- 1: } }}
    • 40. func main() { var c chan int c = make(chan int, 16) go func() { for i := 16; i > 0; i-- { fmt.Print(<-c) } }() produces: go func() { 0110011101011010 select { case c <- 0: case c <- 1: } }() for {}}
    • 41. package generalisetype SignalSource func(status chan bool)func Wait(s SignalSource) { done := make(chan bool) defer close(done) go s(done) <-done}func WaitAll(count int, s SignalSource) { done := make(chan bool) defer close(done) go s(done) for i := 0; i < count; i++ { <- done }}
    • 42. type Iteration func(k, x interface{}) boolfunc (i Iteration) apply(k, v interface{}, c chan bool) { go func() { c <-i(k, v) }()}func (f Iteration) Each(c interface{}) { switch c := ValueOf(c); c.Kind() { case Slice: WaitAll(c.Len(), SignalSource(func(done chan bool) { for i := 0; i < c.Len(); i++ { f.apply(i, c.Elem(i).Interface(), done) }})) case Map: WaitAll(c.Len(), SignalSource(func(done chan bool) { for _, k := range c.Keys() { f.apply(k, c.Elem(k).Interface(), done) }})) }}
    • 43. type Results chan interface{}type Combination func(x, y interface{}) interface{}func (f Combination) Reduce(c, s interface{}) (r Results) { r = make(Results) go func() { Iteration(func(k, x interface{}) (ok bool) { s = f(s, x) return true }).Each(c) r <- s }() return}
    • 44. type Transformation func(x interface{}) interface{}func (t Transformation) Transform(x interface{}) Value { return ValueOf(t(x))}func (t Transformation) Map(c interface{}) (r interface{}) { r = Allocate(c) if i := MapIterator(r); i != nil { i.Each(c) } return}
    • 45. func MapIterator(c interface{}) (i Iteration) { switch n := ValueOf(c); n.Kind() { case Slice: i = Iteration(func(k, x interface{}) bool { n.Elem(k.(int)).SetValue(t.GetValue(x)) return true }) case Map: i = Iteration(func(k, x interface{}) bool { n.SetMapIndex(ValueOf(k), t.GetValue(x)) return true }) } return}
    • 46. func main() { s := []int{0, 1, 2, 3, 4, 5} d := Transformation(func(x interface{}) interface{} { return x.(int) * 2 } ).Map(s) sum := Combination(func(x, y interface{}) interface{} { return x.(int) + y.(int) }) fmt.Printf("s = %v, sum = %vn", s, (<- sum.Reduce(s, 0)).(int)) fmt.Printf("d = %v, sum = %vn", d, (<- sum.Reduce(d, 0)).(int))} produces: s = [0 1 2 3 4 5], sum = 15 d = [0 2 4 6 8 10], sum = 30
    • 47. extensible
    • 48. include $(GOROOT)/src/Make.incTARG=sqlite3CGOFILES= sqlite3.go database.goifeq ($(GOOS),darwin)CGO_LDFLAGS=/usr/lib/libsqlite3.0.dylibelseCGO_LDFLAGS=-lsqlite3endifinclude $(GOROOT)/src/Make.pkg
    • 49. package sqlite3// #include <sqlite3.h>import "C"import "fmt"import "os"type Database struct { handle *C.sqlite3 Filename string Flags C.int}func (db *Database) Error() os.Error { return Errno(C.sqlite3_errcode(db.handle))}
    • 50. const( OK = Errno(iota) ERROR CANTOPEN = Errno(14))var errText = map[Errno]string { ERROR: "SQL error or missing database", CANTOPEN: "Unable to open the database file",}type Errno intfunc (e Errno) String() (err string) { if err = errText[e]; err == "" { err = fmt.Sprintf("errno %v", int(e)) } return}
    • 51. func (db *Database) Open(flags... int) (e os.Error) { db.Flags = 0 for _, v := range flags { db.Flags = db.Flags | C.int(v) } f := C.CString(db.Filename) if err := Errno(C.sqlite3_open_v2(f, &db.handle, db.Flags, nil)); err != OK { e = err } else if db.handle == nil { e = CANTOPEN } return}func (db *Database) Close() { C.sqlite3_close(db.handle) db.handle = nil}
    • 52. func Open(filename string, flags... int) (db *Database, e os.Error) { defer func() { if x := recover(); x != nil { db.Close() db = nil e = ERROR } }() db = &Database{ Filename: filename } if len(flags) == 0 { e = db.Open( C.SQLITE_OPEN_FULLMUTEX, C.SQLITE_OPEN_READWRITE, C.SQLITE_OPEN_CREATE ) } else { e = db.Open(flags...) } return}
    • 53. fun!
    • 54. finding out morehttp://golang.org/twitter://#golightlyhttp://github.com/feyeleanor/wikipedia or google

    ×