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
Generative Programming in Go
Search
monochromegane
June 21, 2015
Technology
7.7k
16
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Generative Programming in Go
GoCon2015発表資料
https://github.com/GoCon/GoCon/blob/master/2015summer.rst
monochromegane
June 21, 2015
More Decks by monochromegane
See All by monochromegane
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
290
適応的スパムフィルタのための軽量な類似メッセージカウンタ / jsai2026-adaptive-spam-filter
monochromegane
0
6.2k
ベクトル検索のフィルタを用いた機械学習モデルとの統合 / python-meetup-fukuoka-06-vector-attr
monochromegane
3
930
Claude Codeセッション現状確認 2026福岡 / fukuoka-aicoding-00-beacon
monochromegane
4
840
Go言語での実装を通して学ぶLLMファインチューニングの仕組み / fukuokago22-llm-peft
monochromegane
0
320
不確実性下における目的と手段の統合的探索に向けた連続腕バンディットの応用 / iot70_gp_rff_mab
monochromegane
2
600
なめらかなシステムと運用維持の終わらぬ未来 / dicomo2025_coherently_fittable_system
monochromegane
0
55k
ベクトル検索システムの気持ち
monochromegane
38
13k
Go言語での実装を通して学ぶ、高速なベクトル検索を支えるクラスタリング技術/fukuokago-kmeans
monochromegane
1
350
Other Decks in Technology
See All in Technology
Technical Project Manager の役割とやりがい、少しだけ AI
yoshiiryo1
0
320
Agent × Maestro で始める モバイル E2E 端末準備からテスト実行・結果確認まで
sansantech
PRO
0
240
AIで選択肢が広がった組織設計の理想と現実
konifar
16
7.1k
200人の配信コメント、 全部Jevが仕分けます 〜 マサカリガードを作ってみた 〜
katayamatg
1
460
(swiftc) NonCopyableとライフタイム修飾子
teamhimeh
0
160
新卒エンジニア、 介護士になる
ryu1013
1
500
バイブコーディングの特徴と「コケて直す」ループ
happysamurai294
0
130
渡米前の準備を制す!re:Invent 2026徹底準備術 / The Ultimate Preparation Guide for re:Invent 2026
yuj1osm
1
440
reInvent2026stby LT00 "Change your life!"
shinichirokawano
1
480
ひとりで始めた AI駆動開発、チームに広げて何が変わったのか
kenichiodo
1
160
推論基盤と Scale-Up Interconnect の現状と制約から俯瞰する技術動向
markunet
2
660
書き手が人でもAIでも正しくなる道、SREを埋め込んだDeveloper Platform / tech drivers day8
chmikata
4
850
Featured
See All Featured
Everyday Curiosity
cassininazir
0
380
Marketing to machines
jonoalderson
1
5.9k
Exploring anti-patterns in Rails
aemeredith
4
550
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
750
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
600
How to Talk to Developers About Accessibility
jct
2
600
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.5k
Utilizing Notion as your number one productivity tool
mfonobong
4
630
How to train your dragon (web standard)
notwaldorf
96
6.9k
The Cult of Friendly URLs
andyhume
79
7k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
43k
Transcript
Generative Programming in Go - GoCon 2015 summer - @monochromegane
MIYAKE Yusuke (@monochromegane)
GMO Pepabo, Inc.
♕ 3 GitHub Awards Go ranking in Japan :)
Generative Programming
ੜతͳ Programming
Generator + Template parse generate Parser Your App Generated Code
AST Code use
Attention, please.
✘ Generics Meta programming Dynamic generation
parse Parser AST Code Go provides
Generator + Template generate Your App Generated Code use We
implement
argen ActiveRecord Generator
GoͰDataMapperͰͳ͘ ActiveRecordϥΠΫʹ DBૢ࡞͢Δ
by Generative programming
ߏମʹ`+AR`ϚʔΧʔΛ͚ͭΔ //+AR type User struct { Id int Name string
Age int }
ੜ͢Δ $ argen main.go $ tree . !"" main.go #""
main_gen.go
ߏମʹARϥΠΫͳϝιου͕ Ճ͞ΕΔ db, _ := sql.Open("sqlite3", "foo.db") Use(db) u :=
User{Name: "test", Age: 20} u.Save() //// INSERT INTO users (name, age) VALUES (?, ?); [test 20] User{}.Where("name", "test").And("age", ">", 20).Query() //// SELECT users.id, users.name, users.age FROM users WHERE name = ? AND age > ?; [test 20]
Generative Programming ͍υίϩ
Case.1 Generics
ҙͷߏମʹڞ௨ͷϝιου Λ࣋ͨͤͭͭɺݸʑͷܕΛѻ͏ var u User u = User{}.First() var h
Hoge h = Hoge{}.First()
ҙͷߏମʹڞ௨ͷϝιου Λ࣋ͨͤͭͭɺݸʑͷܕΛѻ͏ var u User u = User{}.First() var h
Hoge h = Hoge{}.First() • Ωϟετͨ͘͠ͳ͍ • Genericsͷग़൪
ᵆᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᵪᴸᴸᵊ ᴺwhy no generics golangɹ ᴺݕࡧᴺ ᵎᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᴸᵲᴸᴸᵒ
Let’s generate !
ߏମʹରͯ͠ݸʑͷܕΛѻ͏ ڞ௨ͷϝιουΛੜ
func (m User) First() (*User, error) { return m.newRelation().First() }
func (r *UserRelation) First() (*User, error) { return r.Order("id", "ASC").Limit(1).QueryRow() } func (r *UserRelation) QueryRow() (*User, error) { row := &User{} err := r.Relation.QueryRow( row.fieldPtrsByName( r.Relation.GetColumns())...) if err != nil { return nil, err } return row, nil }
see also: clipperhouse/gen // +gen slice:"All" type Person struct {
Name string Present bool } gang := PersonSlice { {"Alice", true}, {"Bob", false}, {"Carly", true}, } here := func(p Person) bool { return p.Present } gang.All(here) // => false, Bob didn't make it
Case.2 Performance
ϦϑϨΫγϣϯΛͬͨ൚༻ੑ ύϑΥʔϚϯεͱҾ͖͑ // Useful! but... var u User db.First(&u)
ϕϯνϚʔΫ // read SomeFunc(s.F) SomeFunc(reflect.ValueOf(s).FieldByName("F").Int()) // write s.F = 100
reflect.ValueOf(&s).Elem().FieldByName("F").SetInt(100) $ go test -benchmem -bench . • Mac OSX(10.10.3) • CPU: 2.5GHz Core i5(2Core) • Memory: 8GB • Go: 1.4.2
ߏମϑΟʔϧυʹର͢ΔΞΫηε time Alloced Bytes Allocs read field 0.38 ns 0
B 0 allocs reflect 246 ns 16 B 2 allocs write field 0.36 ns 0 B 0 allocs reflect 199 ns 8 B 1 allocs
ෳͷߏମϑΟʔϧυʹର͢ΔΞΫηε time Alloced Bytes Allocs read field 0.36 ns 0
B 0 allocs reflect 583 ns 88 B 2 allocs write field 0.37 ns 0 B 0 allocs reflect 277 ns 8 B 1 allocs
Let’s generate !
ߏମʹରͯ͠ϑΟʔϧυใ औಘ༻ϝιουΛੜ
func (m *User) fieldValueByName(name string) interface{} { switch name {
case "id", "users.id": return m.Id case "name", "users.name": return m.Name case "age", "users.age": return m.Age default: return "" } } func (m *User) fieldPtrByName(name string) interface{} { switch name { case "id", "users.id": return &m.Id case "name", "users.name": return &m.Name case "age", "users.age": return &m.Age default: return nil } }
see also: pquerna/ffjson //go:generate ffjson $GOFILE type Foo struct {
Bar string } f := Foo{"bar"} b, _ := json.Marshal(f) fmt.Printf("%s\n", string(b)) // => {"Bar":"bar"} https://github.com/pquerna/ffjson
Case.3 DSL
ҙͷߏମͷڞ௨ϝιου هड़༰͕ʹͳΓ͕ͪ // far from the DSL... func (u *User)
BeforeUpdate() (err error) { if u.Name != "abc"{ return fmt.Errorf("%s is invalid name.", u.Name) } if u.Age > 20 { return fmt.Errorf("%d is invalid age.", u.Age) } return nil }
Let’s generate !
ϝιου໊/ίϝϯτ/λά͔Β ఆٛΛิͯ͠ੜ
func (u User) validatesName() ar.Rule { return ar.MakeRule().Format().With("abc").OnCreate() } func
(u User) validatesAge() ar.Rule { return ar.MakeRule().Numericality().OnlyInteger().LessThan(20) } rules := map[string]*ar.Validation{ "name": m.validatesName().Rule(), "age": m.validatesAge().Rule(), } for name, rule := range rules { if ok, errs := ar.NewValidator(rule).On(on).IsValid(m.fieldValueByName(name)); !ok { result = false errors.SetErrors(name, errs) } } >
Case. Bad
ͳΜͰGenerate
• ϝιουͷڞ௨Խɺଟଶੑͷ࣮ݱͳͲߏମͷຒࠐ (ҕৡ)interfaceΛͬͯΔ͖ • http://go-talks.appspot.com/github.com/lestrrat/ go-slides/2014-yapcasia-go-for-perl-mongers/ main.slide#27 • http://blog.monochromegane.com/blog/ 2014/03/23/struct-implementaion-patterns-in-
golang/ • Generate࣮ଆར༻ଆҰख͔͔ؒΔɺෳࡶ ʹͳΓ͕ͪɻGenerateͰΔཧ༝͕આ໌Ͱ͖ͳ͍ͷ Ͱ͋Ε͏͖Ͱͳ͍
Tips
ίϚϯυϥΠϯ/go generate ͷ྆ํʹରԠ͢Δ
from := os.Getenv("GOFILE") if from == "" { if len(args)
> 0 { from = args[0] } else { os.Exit(1) } } $ argen main.go // go:generate argen
defineΛͬͯ templateΛׂཧ͢Δ
{{template "Relation" .}} {{define "Relation"}} type {{.Name}}Relation struct { src
*{{.Name}} *ar.Relation } {{end}} func (t Template) toDefine() string { return fmt.Sprintf("{{define \"%s\"}}%s{{end}}\n", t.Name, t.Text) } var relation = &Template{ Name: "Relation", Text: ` type {{.Name}}Relation struct { src *{{.Name}} *ar.Relation }`
templateͰ ࣗಈܗͱ ΦʔτΠϯϙʔτ
func writeWithFormat(file, template string, structs structs) ([]byte, error) { var
b bytes.Buffer w := bufio.NewWriter(&b) write(w, template, structs) w.Flush() formatted, err := imports.Process(file, b.Bytes(), nil) if err != nil { return nil, err } return formatted, nil } func write(w io.Writer, tplText string, structs structs) error { t := template.New("t") t.Funcs(template.FuncMap{}) tpl := template.Must(t.Parse(tplText)) if err := tpl.Execute(w, structs); err != nil { return err } return nil }
ςετੜʹ ରͯ͠ߦ͏
//go:generate go run ../cmd/argen/main.go package tests import "github.com/monochromegane/argen" //+AR type
User struct { Name string Age int } $ go generate && go test ./...
એ ϖύϘͰΤϯδχΞΛืू͍ͯ͠·͢ɻ ڞʹαʔϏεΛੜΈग़͠ҭͯͯ͘ΕΔ৽͍ؒ͠ Λ͍ͬͯ·͢ɻ http://pepabo.com/recruit/career/engineer/
͓ΘΓ