Go: It's Not Just For Google
-
Upload
eleanor-mchugh -
Category
Technology
-
view
6.838 -
download
1
description
Transcript of Go: It's Not Just For Google
![Page 1: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/1.jpg)
Goit’s not just for Google
Eleanor McHugh
http://slides.games-with-brains.net/
Rough Cut!
![Page 2: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/2.jpg)
compiled
![Page 3: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/3.jpg)
garbage collected
![Page 4: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/4.jpg)
imperative
![Page 5: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/5.jpg)
package main
import “fmt”
const HELLO string = “hello”var WORLD string = “world”
func main() { fmt.Println(HELLO, WORLD)}
![Page 6: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/6.jpg)
strongly typed
![Page 7: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/7.jpg)
value
boolean, numeric, array
value
structure, interface
reference pointer, slice, string, map, channel
function function, method, closure
![Page 8: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/8.jpg)
underlyingtype
methodset
expressedtype
![Page 9: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/9.jpg)
underlyingtype
methodset
expressedtype
embeddedtypes
![Page 10: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/10.jpg)
package Integer
type Int int
func (i *Int) Add(x int) { *i += Int(x)}
![Page 11: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/11.jpg)
type Buffer []Int
func (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)}
![Page 12: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/12.jpg)
package main
import “fmt”import "Integer"
func main() { i := Integer.Buffer{0, 1, 2, 3, 4, 5} b := i.Clone() b.Swap(1, 2) b.Move(3, 2) b[0].Add(3) fmt.Printf(“b[0:2] = %v\n”, b[0:2])}
produces:b[0:2] = [6 4]
![Page 13: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/13.jpg)
testable
![Page 14: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/14.jpg)
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}
![Page 15: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/15.jpg)
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) }}
![Page 16: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/16.jpg)
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]}
![Page 17: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/17.jpg)
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) }}
![Page 18: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/18.jpg)
include $(GOROOT)/src/Make.inc
TARG=integer
GOFILES=\ integer.go\ vector.go
include $(GOROOT)/src/Make.pkg
![Page 19: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/19.jpg)
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) }}
![Page 20: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/20.jpg)
$ gotest -bench="Benchmark"rm -f _test/scripts.a6g -o _gotest_.6 integer.go vector.go nominal_typing_test.go embedded_typing_benchmark_test.go embedded_typing_test.gorm -f _test/scripts.agopack grc _test/scripts.a _gotest_.6 PASSinteger.BenchmarkVectorSwap200000000 8 ns/opinteger.BenchmarkVectorClone6 10000000 300 ns/op
![Page 21: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/21.jpg)
dynamic
![Page 22: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/22.jpg)
type Adder interface { Add(j int) Subtract(j int) Result() interface{} Reset()}
![Page 23: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/23.jpg)
type IAdder int
func (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)}
![Page 24: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/24.jpg)
type FAdder []float32
func (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]}
![Page 25: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/25.jpg)
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) }}
![Page 26: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/26.jpg)
reflected
![Page 27: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/27.jpg)
package generalise
import "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}
![Page 28: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/28.jpg)
package generalise
import . "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}
![Page 29: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/29.jpg)
func throwsPanic(f func()) (b bool) { defer func() { if x := recover(); x != nil { b = true } }() f() return}
![Page 30: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/30.jpg)
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") }}
![Page 31: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/31.jpg)
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}
![Page 32: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/32.jpg)
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 %v\n", 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) }}
![Page 33: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/33.jpg)
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 %v\n", 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) }}
![Page 34: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/34.jpg)
low-level
![Page 35: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/35.jpg)
package raw
import . "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}
![Page 36: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/36.jpg)
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}
![Page 37: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/37.jpg)
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)}
![Page 38: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/38.jpg)
concurrent
![Page 39: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/39.jpg)
package mainimport "fmt"
func main() { var c chan int c = make(chan int) limit := 16 go func() { for i := limit; i > 0; i-- { fmt.Print(<-c) } }() for i := limit; i > 0; i-- { select { case c <- 0: case c <- 1: } }}
produces:0110011101011010
![Page 40: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/40.jpg)
func main() { var c chan int c = make(chan int, 16) go func() { for i := 16; i > 0; i-- { fmt.Print(<-c) } }() go func() { select { case c <- 0: case c <- 1: } }() for {}}
produces:0110011101011010
![Page 41: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/41.jpg)
package generalise
type 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 }}
![Page 42: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/42.jpg)
type Iteration func(k, x interface{}) bool
func (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) }})) }}
![Page 43: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/43.jpg)
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}
![Page 44: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/44.jpg)
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}
![Page 45: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/45.jpg)
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}
![Page 46: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/46.jpg)
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 = %v\n", s, (<- sum.Reduce(s, 0)).(int)) fmt.Printf("d = %v, sum = %v\n", d, (<- sum.Reduce(d, 0)).(int))}
produces:s = [0 1 2 3 4 5], sum = 15d = [0 2 4 6 8 10], sum = 30
![Page 47: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/47.jpg)
extensible
![Page 48: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/48.jpg)
include $(GOROOT)/src/Make.inc
TARG=sqlite3
CGOFILES=\ sqlite3.go\ database.go
ifeq ($(GOOS),darwin)CGO_LDFLAGS=/usr/lib/libsqlite3.0.dylibelseCGO_LDFLAGS=-lsqlite3endif
include $(GOROOT)/src/Make.pkg
![Page 49: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/49.jpg)
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))}
![Page 50: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/50.jpg)
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 int
func (e Errno) String() (err string) { if err = errText[e]; err == "" { err = fmt.Sprintf("errno %v", int(e)) } return }
![Page 51: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/51.jpg)
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}
![Page 52: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/52.jpg)
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}
![Page 53: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/53.jpg)
fun!
![Page 54: Go: It's Not Just For Google](https://reader033.fdocuments.us/reader033/viewer/2022052315/554a1127b4c90507558b4cf3/html5/thumbnails/54.jpg)
finding out more
http://golang.org/
twitter://#golightly
http://github.com/feyeleanor/
wikipedia or google