Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
reform: путь к лучшему ORM
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Alexey Palazhchenko
May 14, 2016
Programming
650
2
Share
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
180
Песнь Хорьков и Гоферов
aleksi
0
390
Fuzzy generics
aleksi
0
190
On Ferrets and Gophers
aleksi
0
280
How to Go Wrong with Concurrency
aleksi
2
800
Adding context to existing code
aleksi
1
170
Зачем и как написать свой database/sql драйвер
aleksi
1
210
Cooking gRPC
aleksi
1
920
Profiling and Optimizing Go Programs
aleksi
1
1.8k
Other Decks in Programming
See All in Programming
~ 秘伝のタレ化した『神スプシ』と戦う ~ 関数型パラダイムで壊れない仕組みへ
h0r15h0
1
130
Skillは並べた。動かなかった。契約で繋いだ。— 65個のSkillから、自走する開発サイクルへ
junholee
0
720
CLIであることを活かしたGitHub Copilot CLI活用術 / GitHub Copilot CLI Pro Tips & Tricks
nao_mk2
1
980
デフォルト運用のCodeRabbit、1年で何が変わったか / How CodeRabbit Changed Our Code Review in 1 Year
bake0937
1
100
過去のレビュー知見をSkillsで資産化した話
pkshadeck
PRO
1
2.3k
AIエージェントと協働するCLI開発 — BunとOpenClawで学んだこと
yoshikouki
1
210
Old Dog, New Tricks: The Java 25 Reinvention - JNation
bazlur_rahman
0
120
「OSSがあるなら自作するな」は AI時代も正しいか ── Build vs Adopt の新しい判断基準
kumorn5s
7
3k
新規プロダクトを高速で生み出すハーネスエンジニアリング
seanchas116
3
270
密結合なバックエンドから TypeScript のコードを生成する
kemuridama
1
340
oxlintはeslint/typescript-eslintを置き換えられるのか
shomafujita
2
210
Are We Really Coding 10× Faster with AI?
kohzas
0
230
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
340
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
370
Information Architects: The Missing Link in Design Systems
soysaucechin
0
940
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Side Projects
sachag
455
43k
What's in a price? How to price your products and services
michaelherold
247
13k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.2k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Amusing Abliteration
ianozsvald
1
180
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
180
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
560
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