Skip to content

Commit b1c15f0

Browse files
committed
Improve go docs
1 parent c18b036 commit b1c15f0

File tree

3 files changed

+191
-206
lines changed

3 files changed

+191
-206
lines changed

example_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,93 @@ func ExampleReader_NetworksWithin() {
137137
// 1.0.64.0/18: Cable/DSL
138138
// 1.0.128.0/17: Cable/DSL
139139
}
140+
141+
// CustomCity represents a simplified city record with custom unmarshaling.
142+
// This demonstrates the Unmarshaler interface for high-performance decoding.
143+
type CustomCity struct {
144+
Names map[string]string
145+
GeoNameID uint
146+
}
147+
148+
// UnmarshalMaxMindDB implements the maxminddb.Unmarshaler interface.
149+
// This provides significant performance improvements over reflection-based decoding
150+
// by allowing custom, optimized decoding logic for performance-critical applications.
151+
func (c *CustomCity) UnmarshalMaxMindDB(d *maxminddb.Decoder) error {
152+
for key, err := range d.DecodeMap() {
153+
if err != nil {
154+
return err
155+
}
156+
157+
switch string(key) {
158+
case "city":
159+
// Decode nested city structure
160+
for cityKey, cityErr := range d.DecodeMap() {
161+
if cityErr != nil {
162+
return cityErr
163+
}
164+
switch string(cityKey) {
165+
case "names":
166+
// Decode nested map[string]string for localized names
167+
names := make(map[string]string)
168+
for nameKey, nameErr := range d.DecodeMap() {
169+
if nameErr != nil {
170+
return nameErr
171+
}
172+
value, valueErr := d.DecodeString()
173+
if valueErr != nil {
174+
return valueErr
175+
}
176+
names[string(nameKey)] = value
177+
}
178+
c.Names = names
179+
case "geoname_id":
180+
geoID, err := d.DecodeUInt32()
181+
if err != nil {
182+
return err
183+
}
184+
c.GeoNameID = uint(geoID)
185+
default:
186+
if err := d.SkipValue(); err != nil {
187+
return err
188+
}
189+
}
190+
}
191+
default:
192+
// Skip unknown fields to ensure forward compatibility
193+
if err := d.SkipValue(); err != nil {
194+
return err
195+
}
196+
}
197+
}
198+
return nil
199+
}
200+
201+
// This example demonstrates how to use the Unmarshaler interface for high-performance
202+
// custom decoding. Types implementing Unmarshaler automatically use custom decoding
203+
// logic instead of reflection, providing better performance for critical applications.
204+
func ExampleUnmarshaler() {
205+
db, err := maxminddb.Open("test-data/test-data/GeoIP2-City-Test.mmdb")
206+
if err != nil {
207+
log.Fatal(err)
208+
}
209+
defer db.Close() //nolint:errcheck // error doesn't matter
210+
211+
addr := netip.MustParseAddr("81.2.69.142")
212+
213+
// CustomCity implements Unmarshaler, so it will automatically use
214+
// the custom UnmarshalMaxMindDB method instead of reflection
215+
var city CustomCity
216+
err = db.Lookup(addr).Decode(&city)
217+
if err != nil {
218+
log.Panic(err)
219+
}
220+
221+
fmt.Printf("City ID: %d\n", city.GeoNameID)
222+
fmt.Printf("English name: %s\n", city.Names["en"])
223+
fmt.Printf("German name: %s\n", city.Names["de"])
224+
225+
// Output:
226+
// City ID: 2643743
227+
// English name: London
228+
// German name: London
229+
}

internal/decoder/unmarshaler_example_test.go

Lines changed: 0 additions & 206 deletions
This file was deleted.

0 commit comments

Comments
 (0)