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
Fuzzy generics
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Alexey Palazhchenko
February 05, 2022
Programming
200
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Fuzzy generics
Alexey Palazhchenko
February 05, 2022
More Decks by Alexey Palazhchenko
See All by Alexey Palazhchenko
Using PostgreSQL's Background Worker Processes For Fun and Profit
aleksi
0
200
Песнь Хорьков и Гоферов
aleksi
0
400
On Ferrets and Gophers
aleksi
0
290
How to Go Wrong with Concurrency
aleksi
2
820
Adding context to existing code
aleksi
1
180
Зачем и как написать свой database/sql драйвер
aleksi
1
220
Cooking gRPC
aleksi
1
940
Profiling and Optimizing Go Programs
aleksi
1
1.8k
Go: начало
aleksi
0
150
Other Decks in Programming
See All in Programming
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.5k
Google Apps Script で Ruby を動かす
kawahara
0
150
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
200
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
130
React本体のコードリーディング
high_g_engineer
1
140
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
470
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
320
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
180
freee が目指す データ マネジメント戦略 AI-Ready 時代を支える 攻めのガバナンスとは
freee
PRO
0
350
Built Our Own Background Agent at LayerX
layerx
PRO
10
5.3k
Building a Meta Ray-Ban display app
akkeylab
0
100
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
1
1.6k
Featured
See All Featured
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
400
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
250
Balancing Empowerment & Direction
lara
6
1.2k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
460
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
210
Accessibility Awareness
sabderemane
1
170
Making Projects Easy
brettharned
120
6.7k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
990
Transcript
Fuzzy generics Several months of using 1.18 features Alexey Palazhchenko
FOSDEM 2022-02-05
None
Why Go 1.18?
Why Go 1.18? Generics
Why Go 1.18? Generics Fuzzing
Why Go 1.18? Generics Fuzzing
Generics
Generics • Generics do not work there; let's go back
to interfaces
Generics • Generics do not work there; let's go back
to interfaces • Let me extract a small example for a talk
Generics • Generics do not work there; let's go back
to interfaces • Let me extract a small example for a talk • Hm, that's not that bad
BSON Document
BSON Document • Ordered map
BSON Document • Ordered map • Keys – string, values
– any BSON value, including other documents
BSON Document • Ordered map • Keys – string, values
– any BSON value, including other documents • The central data structure in FerretDB
Interfaces type BSONType interface { bsontype() // sealed } type
Int int func (Int) bsontype() {} type String string func (String) bsontype() {}
Interfaces type BSONType interface { bsontype() // sealed } type
Int int func (Int) bsontype() {} type String string func (String) bsontype() {} type Document struct { m map[string]BSONType keys []string } func (*Document) bsontype() {}
Interfaces func (d *Document) Set(key String, value BSONType) { if
_, ok := d.m[key]; !ok { d.keys = append(d.keys, key) } d.m[key] = value }
Interfaces d.Set("foo", Int(42))
Interfaces d.Set("foo", Int(42)) d.Set("qux", nil)
Generics type BSONType interface { int | string | *Document
}
Generics type BSONType interface { int | string | *Document
} type Document struct { m map[string]any keys []string }
Generics func (d *Document) Set[T BSONType](key string, value T) {
if _, ok := d.m[key]; !ok { d.keys = append(d.keys, key) } d.m[key] = value }
Generics func (d *Document) Set[T BSONType](key string, value T) {
if _, ok := d.m[key]; !ok { d.keys = append(d.keys, key) } d.m[key] = value } syntax error: method must have no type parameters
Generics func DocumentSet[T BSONType](d *Document, key string, value T) {
if _, ok := d.m[key]; !ok { d.keys = append(d.keys, key) } d.m[key] = value }
Generics DocumentSet(d, "foo", 42)
Generics DocumentSet(d, "foo", 42) // DocumentSet(d, "qux", nil)
Interfaces func MakeDocument(pairs ...BSONType) (*Document, error) { l := len(pairs)
if l%2 != 0 { return nil, fmt.Errorf("%d arguments", l)
Interfaces
Interfaces MakeDocument( String("foo"), Int(42), String("bar"), String("baz"), )
Interfaces MakeDocument( String("foo"), Int(42), String("bar"), String("baz"), ) MakeDocument(String("invalid number of
arguments"))
Interfaces MakeDocument( String("foo"), Int(42), String("bar"), String("baz"), ) MakeDocument(String("invalid number of
arguments")) MakeDocument(Int(42), String("invalid key type"))
Generics
Generics func MakeDocument[T BSONType](key string, value T) *Document
Generics func MakeDocument[T BSONType](key string, value T) *Document func MakeDocument2[T1,
T2 BSONType](key1 string, value1 T1, key2 string, value2 T2) *Document
Generics func MakeDocument[T BSONType](key string, value T) *Document func MakeDocument2[T1,
T2 BSONType](key1 string, value1 T1, key2 string, value2 T2) *Document func MakeDocument3[T1, T2, T3 BSONType](key1 string, value1 T1, key2 string, value2 T2, key3 string, value3 T3) *Document
Interfaces
Interfaces func (d *Document) Get(key String) BSONType { return d.m[key]
}
Interfaces func (d *Document) Get(key String) BSONType { return d.m[key]
} assert.Equal(t, Int(42), d.Get("foo")) assert.Equal(t, nil, d.Get("baz"))
Generics
Generics func DocumentGet[T BSONType](d *Document, key string) T { v,
_ := d.m[key].(T) return v }
Generics func DocumentGet[T BSONType](d *Document, key string) T { v,
_ := d.m[key].(T) return v } assert.Equal(t, 42, DocumentGet[int](d, "foo")) assert.Equal(t, "", DocumentGet[string](d, "foo"))
Generics vs Interfaces
Generics vs Interfaces • Better in some aspects
Generics vs Interfaces • Better in some aspects • Worse
in others
Generics vs Interfaces • Better in some aspects • Worse
in others
Fuzzing
Fuzzing • testing/quick on steroids
Fuzzing • testing/quick on steroids • MongoDB binary protocol parsing
packages
Fuzzing • testing/quick on steroids • MongoDB binary protocol parsing
packages • FerretDB had fuzzing tests even before unit tests
Table-driven tests type testCase struct { name string b []byte
v bsontype err error }
Table-driven tests type testCase struct { name string b []byte
v bsontype err error } • Unmarshal b to (v2, err2) • compare with v or err • Marshal v2 to b2 • compare with b
Table-driven tests func TestDocument(t *testing.T) { for _, tc :=
range testCases { tc := tc t.Run(tc.name, func(t *testing.T) {
Fuzzing func FuzzDocument(f *testing.F) { for _, tc := range
testCases { f.Add(tc.b) } f.Fuzz(func(t *testing.T, b []byte) {
When b2 != b
When b2 != b • b might be larger than
needed
When b2 != b • b might be larger than
needed • The unread portion of b should be removed
When b2 != b • b might be larger than
needed • The unread portion of b should be removed • Some bytes might be insigni fi cant
When b2 != b • b might be larger than
needed • The unread portion of b should be removed • Some bytes might be insigni fi cant • Use canonization (json.Compact, etc)
Fuzzing issues
Fuzzing issues • No subtests (testing.F.Run)
Fuzzing issues • No subtests (testing.F.Run) • Unnamed seed values
Fuzzing issues • No subtests (testing.F.Run) • Unnamed seed values
• Hanging detection is unreliable with unset GOMAXPROCS
Fuzzing
Fuzzing • Found a few bugs in `go test -fuzz`
Fuzzing • Found a few bugs in `go test -fuzz`
• Found many many bugs in FerretDB
Fuzzing • Found a few bugs in `go test -fuzz`
• Found many many bugs in FerretDB • De fi nitely use it for parsing
Links • https://github.com/AlekSi/ generics-vs-interfaces • https://github.com/akutz/ go-generics-the-hard-way • https://go.dev/doc/tutorial/ •
https://go.dev/doc/fuzz/ • https://www.ferretdb.io • https://github.com/FerretDB ⭐ • https://github.com/AlekSi • @paaleksey