|
| 1 | +# Migrating from v1 to v2 |
| 2 | + |
| 3 | +## Package import |
| 4 | + |
| 5 | +```go |
| 6 | +- import "github.com/oschwald/maxminddb-golang" |
| 7 | ++ import "github.com/oschwald/maxminddb-golang/v2" |
| 8 | +``` |
| 9 | + |
| 10 | +## Lookup API |
| 11 | + |
| 12 | +- v1: `err := reader.Lookup(net.IP, &result)` |
| 13 | +- v2: `err := reader.Lookup(netip.Addr).Decode(&result)` |
| 14 | + |
| 15 | +### Migration tips |
| 16 | + |
| 17 | +- Replace `net.IP` inputs with `net/netip`. Use `netip.ParseAddr` or |
| 18 | + `addr.AsSlice()` helpers when interoperating with code that still expects |
| 19 | + `net.IP`. |
| 20 | +- The new `Result` type returned from `Lookup` exposes `Decode` and |
| 21 | + `DecodePath` methods. Update call sites to chain `Decode` or `DecodePath` |
| 22 | + instead of passing the destination pointer to `Lookup`. |
| 23 | + |
| 24 | +## Manual decoding improvements |
| 25 | + |
| 26 | +- Custom types can implement `UnmarshalMaxMindDB(d *maxminddb.Decoder) error` |
| 27 | + to skip reflection and zero allocations for hot paths. |
| 28 | +- `maxminddb.Decoder` mirrors the APIs from `internal/decoder`, giving fine |
| 29 | + grained access to the underlying data section. |
| 30 | +- `DecodePath` works on the result object, supporting nested lookups without |
| 31 | + decoding entire records. |
| 32 | + |
| 33 | +## Opening databases from byte slice |
| 34 | + |
| 35 | +- v1: `reader, err := maxminddb.FromBytes(databaseBytes)` |
| 36 | +- v2: `reader, err := maxminddb.OpenBytes(databaseBytes)` |
| 37 | + |
| 38 | +## Network iteration |
| 39 | + |
| 40 | +- `Reader.Networks()` and `Reader.NetworksWithin()` now yield iterators that |
| 41 | + work efficiently with Go 1.23+ `range` syntax: |
| 42 | + |
| 43 | + ```go |
| 44 | + for result := range reader.Networks() { |
| 45 | + var record struct { |
| 46 | + ConnectionType string `maxminddb:"connection_type"` |
| 47 | + } |
| 48 | + |
| 49 | + if err := result.Decode(&record); err != nil { |
| 50 | + return err |
| 51 | + } |
| 52 | + fmt.Println(result.Prefix(), record.ConnectionType) |
| 53 | + } |
| 54 | + ``` |
| 55 | + |
| 56 | +- Replace the v1 iterator pattern (`for networks.Next() { ... networks.Network(&record) }`) |
| 57 | + with the Go 1.23 iteration shown above. `Decode` returns any iterator or |
| 58 | + lookup error, so separate calls to `Result.Err()` are rarely needed. |
| 59 | +- Options such as `SkipAliasedNetworks` now use an options pattern. Pass them as |
| 60 | + `Networks(SkipAliasedNetworks())` or `NetworksWithin(prefix, SkipEmptyValues())`. |
| 61 | +- New helpers include `SkipEmptyValues()` to omit entries with empty maps and |
| 62 | + `IncludeNetworksWithoutData()` to keep networks that lack data records. |
| 63 | + |
| 64 | +## Additional API additions |
| 65 | + |
| 66 | +- `Reader.Verify()` validates the database structure and metadata, exposing |
| 67 | + precise `InvalidDatabaseError` messages when corruption is detected. |
| 68 | +- `Metadata.BuildTime()` converts the build epoch to `time.Time`. |
| 69 | +- `Result.DecodePath` now supports negative indices for arrays, matching |
| 70 | + Go slices: `result.DecodePath(&value, "array", -1)` fetches the last element. |
| 71 | + |
| 72 | +## Error handling |
| 73 | + |
| 74 | +- All decoder and verifier errors wrap `mmdberrors.InvalidDatabaseError`, which |
| 75 | + carries offset and JSON Pointer style path clues. Display those details to |
| 76 | + speed up debugging malformed databases. |
| 77 | + |
| 78 | +For more background on the architectural changes, see the per-release notes in |
| 79 | +`CHANGELOG.md`. |
0 commit comments