Ro u                                            gh                                       Cut                              ...
compiled
garbage collected
imperative
package mainimport “fmt”const HELLO string = “hello”var WORLD string = “world”func main() {	   fmt.Println(HELLO, WORLD)}
strongly typed
boolean, numeric, array value                    structure, interfacereference   pointer, slice, string, map, channelfunct...
underlying               method  type                    set             expressed                type
underlying               method  type                    set             expressed                type             embedde...
package Integertype Int intfunc (i *Int) Add(x int) {	   *i += Int(x)}
type Buffer []Intfunc (b Buffer) Swap(i, j int) {	   b[i], b[j] = b[j], b[i]}func (b Buffer) Clone() Buffer {	   s := make...
package mainimport “fmt”import "Integer"func main() {	   i := Integer.Buffer{0, 1, 2, 3, 4, 5}   produces:	   b := i.Clone...
testable
func (b Buffer) Eq(o Buffer) (r bool) {	   if len(b) == len(o) {	   	     for i := len(b) - 1; i > 0; i-- {	   	     	    ...
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...
package Vectorimport . "Integer"type Vector struct {	   Buffer}func (v *Vector) Clone() *Vector {	   return &Vector{v.Buff...
package Vectorimport "testing"func TestVectorSwap(t *testing.T) {	   i := Vector{Buffer{0, 1, 2, 3, 4, 5}}	   v := i.Clone...
include $(GOROOT)/src/Make.incTARG=integerGOFILES=	  integer.go	  vector.goinclude $(GOROOT)/src/Make.pkg
func BenchmarkVectorClone6(b *testing.B) {	   v := Vector{Buffer{0, 1, 2, 3, 4, 5}}	   for i := 0; i < b.N; i++ {	   	    ...
$ gotest -bench="Benchmark"rm -f _test/scripts.a6g -o _gotest_.6 integer.go vector.go nominal_typing_test.goembedded_typin...
dynamic
type Adder interface {	   Add(j int)	   Subtract(j int)	   Result() interface{}	   Reset()}
type IAdder intfunc (i IAdder) Add(j int) {	   i[0] += i[j]}func (i IAdder) Subtract(j int) {	   i[0] -= i[j]}func (i IAdd...
type FAdder []float32func (f FAdder) Add(j int) {	   f[0] += f[j]}func (f FAdder) Subtract(j int) {	   f[0] -= f[j]}func (f...
func TestAdder(t *testing.T) {	   var a	 Adder	   a = IAdder{0, 1, 2}	   a.Add(1)	   if i.Result().(int) != 1 {	   	     t...
reflected
package generaliseimport "reflect"func Allocate(i interface{}, limit... int) (n interface{}) {	   switch v := reflect.ValueO...
package generaliseimport . "reflect"func Allocate(i interface{}, limit... int) (n interface{}) {	   switch v := ValueOf(i);...
func throwsPanic(f func()) (b bool) {	   defer func() {	   	    if x := recover(); x != nil {	   	    	     b = true	   	 ...
func TestAllocate(t *testing.T) {	   var s2 []int	   s1 := []int{0, 1, 2}	   m := map[int] int{1: 1, 2: 2, 3: 3}	   switch...
func Duplicate(i interface{}) (clone interface{}) {	   if clone = Allocate(i); clone != nil {	   	     switch clone := Val...
func TestDuplicateSlice(t *testing.T) {	   s1 := []int{0, 1, 2}	   var s2 []int	   if throwsPanic(func() { s2 = Duplicate(...
func TestDuplicateMap(t *testing.T) {	   m1 := map[int]int{1: 1, 2: 2, 3: 3}	   var m2 map[int]int	   if throwsPanic(func(...
low-level
package rawimport . "reflect"import "unsafe"var _BYTE_SLICE Type = Typeof([]byte(nil))type MemoryBlock interface {	   ByteS...
func SliceHeader(i interface{}) (Header *SliceHeader, Size, Align int) {	   switch value := Indirect(ValueOf(i)); value.Ki...
func ByteSlice(i interface{}) []byte {	   switch i := i.(type) {	   case []byte:	 	      	   	     return i	   case Memory...
concurrent
package mainimport "fmt"func main() {	   var c chan int	   c = make(chan int)	   limit := 16	   go func() {	   	     for i...
func main() {	   var c chan int	   c = make(chan int, 16)	   go func() {	   	     for i := 16; i > 0; i-- {	   	     	    ...
package generalisetype SignalSource func(status chan bool)func Wait(s SignalSource) {	   done := make(chan bool)	   defer ...
type Iteration func(k, x interface{}) boolfunc (i Iteration) apply(k, v interface{}, c chan bool) {	   go func() {	   	   ...
type Results chan interface{}type Combination func(x, y interface{}) interface{}func (f Combination) Reduce(c, s interface...
type Transformation func(x interface{}) interface{}func (t Transformation) Transform(x interface{}) Value {	   return Valu...
func MapIterator(c interface{}) (i Iteration) {	   switch n := ValueOf(c); n.Kind() {	   case Slice:	 	     i = Iteration(...
func main() {	   s := []int{0, 1, 2, 3, 4, 5}	   d := Transformation(func(x interface{}) interface{} {	   	    return x.(i...
extensible
include $(GOROOT)/src/Make.incTARG=sqlite3CGOFILES=	  sqlite3.go	  database.goifeq ($(GOOS),darwin)CGO_LDFLAGS=/usr/lib/li...
package sqlite3// #include <sqlite3.h>import "C"import "fmt"import "os"type Database struct {	   handle	 	    	     	   *C...
const(	   OK	 	 	   = Errno(iota)	   ERROR	   CANTOPEN	 = Errno(14))var errText = map[Errno]string {	    ERROR: 	    	    ...
func (db *Database) Open(flags... int) (e os.Error) {	   db.Flags = 0	   for _, v := range flags {	   	     db.Flags = db.Fl...
func Open(filename string, flags... int) (db *Database, e os.Error) {	   defer func() {	   	     if x := recover(); x != nil...
fun!
finding out morehttp://golang.org/twitter://#golightlyhttp://github.com/feyeleanor/wikipedia or google
Upcoming SlideShare
Loading in …5
×

Go: It's Not Just For Google

7,297 views

Published on

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
7,297
On SlideShare
0
From Embeds
0
Number of Embeds
73
Actions
Shares
0
Downloads
109
Comments
0
Likes
12
Embeds 0
No embeds

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
  • Go: It's Not Just For Google

    1. 1. Ro u gh Cut !Goit’s not just for GoogleEleanor McHughhttp://slides.games-with-brains.net/
    2. 2. compiled
    3. 3. garbage collected
    4. 4. imperative
    5. 5. package mainimport “fmt”const HELLO string = “hello”var WORLD string = “world”func main() { fmt.Println(HELLO, WORLD)}
    6. 6. strongly typed
    7. 7. boolean, numeric, array value structure, interfacereference pointer, slice, string, map, channelfunction function, method, closure
    8. 8. underlying method type set expressed type
    9. 9. underlying method type set expressed type embedded types
    10. 10. package Integertype Int intfunc (i *Int) Add(x int) { *i += Int(x)}
    11. 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. 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. 13. testable
    14. 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. 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. 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. 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. 18. include $(GOROOT)/src/Make.incTARG=integerGOFILES= integer.go vector.goinclude $(GOROOT)/src/Make.pkg
    19. 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. 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. 21. dynamic
    22. 22. type Adder interface { Add(j int) Subtract(j int) Result() interface{} Reset()}
    23. 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. 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. 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. 26. reflected
    27. 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. 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. 29. func throwsPanic(f func()) (b bool) { defer func() { if x := recover(); x != nil { b = true } }() f() return}
    30. 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. 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. 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. 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. 34. low-level
    35. 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. 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. 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. 38. concurrent
    39. 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. 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. 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. 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. 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. 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. 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. 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. 47. extensible
    48. 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. 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. 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. 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. 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. 53. fun!
    54. 54. finding out morehttp://golang.org/twitter://#golightlyhttp://github.com/feyeleanor/wikipedia or google

    ×