Slide 1

Slide 1 text

Go & ORM Yo-An Lin (c9s) Go 吧你 Monday, August 5, 13

Slide 2

Slide 2 text

• Yo-An Lin • Twitter: @c9s • GitHub: c9s • Go, PHP, Perl Monday, August 5, 13

Slide 3

Slide 3 text

What’s Go? Monday, August 5, 13

Slide 4

Slide 4 text

Go aims to combine the safety and performance of a statically typed compiled language with the expressiveness and convenience of a dynamically typed interpreted language. - Rob Pike Monday, August 5, 13

Slide 5

Slide 5 text

History • End of 2007 start by Rob Pike, Ken Thompson and Robert Griesemer. • Implementation started after design in mid 2008. • Going public in November 2009. • Release of Go 1 in March 2012. Monday, August 5, 13

Slide 6

Slide 6 text

Background • Rob Pike • Unix, Plan 9, Inferno, Limbo, UTF-8 • Ken Thompson • Multics, Unix, Plan 9, ed, UTF-8 • Turning Award Monday, August 5, 13

Slide 7

Slide 7 text

Pros & Cons • Performance • Concurrency • Statically typed & Dynamically typed. • Safety • Low Memory Footprint (compared to Java) Monday, August 5, 13

Slide 8

Slide 8 text

Reduce Energy Costs and Go Green How We Went from 30 Servers to 2: Go http://blog.iron.io/2013/03/how-we-went-from-30-servers-to-2-go.html Monday, August 5, 13

Slide 9

Slide 9 text

Success Stories • Airbrake: From Ruby to Go • Go at Heroku • Organizations using Go: Canonical, BBC, Heroku, SmugMug, SoundCloud, Bitly.... Monday, August 5, 13

Slide 10

Slide 10 text

Overview of Go Monday, August 5, 13

Slide 11

Slide 11 text

Hello World package main import "fmt" func main() { !fmt.Println("Hello World") } Monday, August 5, 13

Slide 12

Slide 12 text

func CreateUser(id int64, name string) { ! // ... } Function Monday, August 5, 13

Slide 13

Slide 13 text

Struct Type package main type User struct { !Id int64 !Name string } Monday, August 5, 13

Slide 14

Slide 14 text

package main type User struct { } func (self * User) Create() int64 { } Type Method Monday, August 5, 13

Slide 15

Slide 15 text

user := User{} pUser := &User{} Allocation Monday, August 5, 13

Slide 16

Slide 16 text

type Sequence []int // Methods required by sort.Interface. func (s Sequence) Len() int { return len(s) } func (s Sequence) Less(i, j int) bool { return s[i] < s[j] } func (s Sequence) Swap(i, j int) { s[i], s[j] = s[j], s[i] } Interface Monday, August 5, 13

Slide 17

Slide 17 text

Type Assertion type Stringer interface { String() string } var value interface{} // Value provided by caller. switch str := value.(type) { case string: return str case Stringer: return str.String() } Monday, August 5, 13

Slide 18

Slide 18 text

Why Do We Need An ORM for Go? Monday, August 5, 13

Slide 19

Slide 19 text

More on Effective Go http://golang.org/doc/effective_go.html Monday, August 5, 13

Slide 20

Slide 20 text

Real World Usage • 10+ Tables • A lot of CRUD operations in different methods. • We want performance for hot spots, for other situations, we don’t. Monday, August 5, 13

Slide 21

Slide 21 text

Read Operation (1) ! query := `SELECT id, name, phone, cell_phone, address FROM users WHERE id = $1` ! userId := 10 ! r, err := db.Query(query, userId) ! if err != nil { ! ! t.Fatal(err) ! } ! defer r.Close() Monday, August 5, 13

Slide 22

Slide 22 text

Read Operation (2) ! if !r.Next() { ! ! if r.Err() != nil { ! ! ! t.Fatal(r.Err()) ! ! } ! ! t.Fatal("expected row") ! } Monday, August 5, 13

Slide 23

Slide 23 text

Read Operation (3) ! var id int64 ! var name string ! var phone string ! var cell_phone string ! var address string ! err = r.Scan(&id, &name, &phone, &cell_phone, &address) ! if err != nil { ! ! t.Fatal(err) ! } Monday, August 5, 13

Slide 24

Slide 24 text

And That Is Only For Selecting Record(s).... Monday, August 5, 13

Slide 25

Slide 25 text

Let’s say you have 60+ tables Monday, August 5, 13

Slide 26

Slide 26 text

And you need to do CRUD operations on all of them. Monday, August 5, 13

Slide 27

Slide 27 text

60 X 4 (CRUD) = 240 (Methods) Monday, August 5, 13

Slide 28

Slide 28 text

240 X 20 (Avg. Lines) = 4800 (Lines) Monday, August 5, 13

Slide 29

Slide 29 text

We need something more dynamic & flexible Monday, August 5, 13

Slide 30

Slide 30 text

type Staff struct { ! Id int64 `field:"id"` ! Name string `field:"name"` ! Gender string `field:"gender"` ! StaffType string `field:"staff_type"` ! Phone string `field:"phone"` } put model fields in struct Monday, August 5, 13

Slide 31

Slide 31 text

Reflection Monday, August 5, 13

Slide 32

Slide 32 text

Reflection • Retrieve information dynamically (in the runtime): • Type Name • Struct Fields • Struct Tag • Struct Field Type • Function Type • ....etc Monday, August 5, 13

Slide 33

Slide 33 text

Struct Metadata type Staff struct { ! Id int64 `json:"id"` ! Name string `json:"name"` ! Gender string `json:"gender"` ! StaffType string `json:"staff_type"` ! Phone string `json:"phone"` } Type Name Fields Field Type Struct Tag Tag Key Monday, August 5, 13

Slide 34

Slide 34 text

Reflection import "reflect" staff := new(Staff) // get reflection value of pointer t := reflect.ValueOf(staff) // get reflection value t := reflect.ValueOf(staff).Elem() Monday, August 5, 13

Slide 35

Slide 35 text

Reflection t := reflect.ValueOf(val).Elem() typeOfT := t.Type() for i := 0; i < t.NumField(); i++ { // do something } Monday, August 5, 13

Slide 36

Slide 36 text

var tag reflect.StructTag = typeOfT.Field(i).Tag var json := tag.Get(“json”) Reflection Monday, August 5, 13

Slide 37

Slide 37 text

Reflection t.Field(i).SetInt(keyValue) Struct Value Type Struct Field Monday, August 5, 13

Slide 38

Slide 38 text

SQLUtil Monday, August 5, 13

Slide 39

Slide 39 text

SQLUtil • Table name conversion by inflector http://bitbucket.org/chrisfarms/inflect • Select, Insert, Update, Delete.. basic SQL clause generation. • https://github.com/c9s/gatsby/sqlutils Monday, August 5, 13

Slide 40

Slide 40 text

SQLUtil: Using Inflector package sqlutils import "reflect" import "github.com/c9s/inflect" func GetTableNameFromTypeName(typeName string) string { ! if cache, ok := tableNameCache[typeName]; ok { ! ! return cache ! } ! tableNameCache[typeName] = inflect.Tableize(typeName) ! return tableNameCache[typeName] } Monday, August 5, 13

Slide 41

Slide 41 text

func GetTableName(val interface{}) string { ! typeName := reflect.ValueOf(val).Elem().Type().Name() ! return GetTableNameFromTypeName(typeName) } SQLUtil: Using Inflector Monday, August 5, 13

Slide 42

Slide 42 text

SQLUtil: Select Clause // Given a struct object, return a "SELECT ... FROM {tableName}" SQL clause. func BuildSelectClause(val interface{}) string { ! tableName := GetTableName(val) ! return "SELECT " + BuildSelectColumnClauseFromStruct(val) + " FROM " + tableName } Monday, August 5, 13

Slide 43

Slide 43 text

ActiveRecord Pattern Monday, August 5, 13

Slide 44

Slide 44 text

staff := Staff{} staff.Name = "John" staff.Address = "...." staff.Phone = "076458882" result := staff.Create() Monday, August 5, 13

Slide 45

Slide 45 text

No Problem Monday, August 5, 13

Slide 46

Slide 46 text

Gatsby go  get  github.com/c9s/gatsby Monday, August 5, 13

Slide 47

Slide 47 text

Gatsby ORM • Support PostgreSQL • Transaction support. • Dynamic CRUD Monday, August 5, 13

Slide 48

Slide 48 text

import "gatsby" type Staff struct { ! Id int64 `field:",primary,serial"` ! Name string `field:",required"` ! Gender string `field:"gender"` ! Phone string `field:"phone"` ! gatsby.BaseRecord } Embedded Type Monday, August 5, 13

Slide 49

Slide 49 text

func (self *Staff) Init() { ! self.SetTarget(self) } Call gatsby.BaseRecord.SetTarget 呼叫 Parent method 時, Parent method 拿不到 current instance, 只能拿到 BaseRecord ⾃自⼰己 Monday, August 5, 13

Slide 50

Slide 50 text

result := staff.Create() gatsby.Create() # not found gatsby.BaseRecord.Create() gatsby.BaseRecord.GetTarget() .... Monday, August 5, 13

Slide 51

Slide 51 text

res := staff.Create() if res.Error != nil { !log.Println(res.Sql) !panic(res.Error) } Error Handling Monday, August 5, 13

Slide 52

Slide 52 text

⼯工商服務時間 Monday, August 5, 13

Slide 53

Slide 53 text

GoTray http://gotray.extremedev.org Monday, August 5, 13

Slide 54

Slide 54 text

Thank you Questions? Monday, August 5, 13