Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
reform: путь к лучшему ORM
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Alexey Palazhchenko
May 14, 2016
Programming
680
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
reform: путь к лучшему ORM
Alexey Palazhchenko
May 14, 2016
More Decks by Alexey Palazhchenko
See All by Alexey Palazhchenko
Using PostgreSQL's Background Worker Processes For Fun and Profit
aleksi
0
220
Песнь Хорьков и Гоферов
aleksi
0
400
Fuzzy generics
aleksi
0
210
On Ferrets and Gophers
aleksi
0
310
How to Go Wrong with Concurrency
aleksi
2
830
Adding context to existing code
aleksi
1
190
Зачем и как написать свой database/sql драйвер
aleksi
1
230
Cooking gRPC
aleksi
1
950
Profiling and Optimizing Go Programs
aleksi
1
1.8k
Other Decks in Programming
See All in Programming
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
1.2k
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
200
Lambda durable functionsでHuman in the Loopを楽に…楽に……
har1101
2
230
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
300
オーケストレーション記述言語 Katari
yukikurage
0
210
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
390
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
240
Performance Optimization With LLMs
xleitix
0
230
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
220
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
3
630
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
250
Coding with AI: How to trust the storyteller (AWS Community Day Adria, Ljubljana 2026)
slobodan
0
130
Featured
See All Featured
Leo the Paperboy
mayatellez
10
2.4k
Everyday Curiosity
cassininazir
0
380
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
4
4.4k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
730
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
We Are The Robots
honzajavorek
0
410
YesSQL, Process and Tooling at Scale
rocio
174
15k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7k
Crafting Experiences
bethany
1
390
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Making the Leap to Tech Lead
cromwellryan
135
10k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Transcript
reform путь к лучшему ORM Алексей Палажченко mc² software
None
Цели database/sql src/database/sql/doc.txt • generic database API for SQL/SQL-like, feel
like Go • common cases, portable, no quirks • consistent but flexible type conversions • concurrency, thread safety, built-in pool • push complexity to drivers via optional interfaces
Интерфейс database/sql • DB: Open, Close, Begin, Prepare, Driver •
DB, Stmt, Tx: Query, QueryRow, Exec • Rows: Next, Scan, Err, Close • Result: LastInsertId, RowsAffected • NullBool, NullInt64, NullFloat64, NullString • Scanner: Scan(src interface{}) error
INSERT result, err := db.Exec( "INSERT INTO users (name) "+
"VALUES ($1)", "gopher" )
SELECT defer rows.Close() for rows.Next() { var name string if
e := rows.Scan(&name); e != nil { log.Fatal(e) } fmt.Println(name) } if e := rows.Err(); e != nil { log.Fatal(e) }
Интерфейс database/sql/driver • Value: пустой интерфейс • ValueConverter: ConvertValue(v interface{})
(Value, error) • Valuer: Value() (Value, error)
database/sql/driver.Value • nil • int64 • float64 • bool •
[]byte (non-nil) • string everywhere except from Rows.Next. #6497 • time.Time (боль с часовыми зонами)
Свои типы func (j JSONText) Value() (driver.Value, error) { if
j == nil { return nil, nil } var m json.RawMessage err := json.Unmarshal(j, &m) if err != nil { return []byte{}, err } return []byte(j), nil }
Свои типы func (j *JSONText) Scan(value interface{}) error { if
value == nil { *j = nil return nil } v, ok := value.([]byte) if !ok { return fmt.Errorf("error") } *j = JSONText(append((*j)[0:0], v...)) return nil }
Драйвера • github.com/golang/go/wiki/SQLDrivers • github.com/bradfitz/go-sql-test
Зачем ORM?
INSERT result, err := db.Exec( "INSERT INTO users (name) "+
"VALUES ($1)", "gopher" )
SELECT defer rows.Close() for rows.Next() { var name string if
e := rows.Scan(&name); e != nil { log.Fatal(e) } fmt.Println(name) } if e := rows.Err(); e != nil { log.Fatal(e) }
ORM • Не-ORM / малые ORM (например, отображение Scan строк
в структуры) • Большие ORM
ORM func Save(m interface{}) error
ORM Save(User{Name: "gopher"}) Save(&User{Name: "gopher"}) Save(nil) Save(42) Save("Batman!!")
Идея: struct для данных type Person struct { ID int64
`sql:"id,omitempty"` Name string `sql:"name,omitempty"` }
Идея: непустые интерфейсы type Record interface { Values() []interface{} Pointers()
[]interface{} PrimaryKeyPointer() interface{} SetPrimaryKey(id interface{}) Table() Table } funс Save(record Record) error
Идея: генерация кода • struct и код из XML •
XML из information_schema • struct пишется, код генерируется из него
Проблемы: Go vs SQL • SQL: значения по-умолчанию • SQL:
отсутствие в запросе • Go: zero value
person := &Person{ Name: "gopher", } if err := DB.Save(person);
err != nil { log.Fatal(err) }
Что почитать • Документацию database/sql/… • Код database/sql/… • github.com/mc2soft/pq-types
• github.com/AlekSi/reform
• https://groups.google.com/forum/#!forum/golang-ru • http://www.meetup.com/Golang-Moscow/ • http://4gophers.ru • http://4gophers.ru/slack • https://golangshow.com