Golang 1.23: new unique package

A cheap way to compare complex objects

分享
Golang 1.23: new unique package
Generate By DALLE-3

Last week, Go 1 .23 entered the freeze period, meaning no new features will be added, and any already added features are unlikely to be removed. This is a great opportunity to preview the upcoming changes. In this article, we will introduce the new package unique

Go 1.23 Forward-looking
Edit description

According to wikipedia , interning is to reuse objects with equal values on demand. The technology reduces the action of creating new objects. This creation mode is often used for numbers and strings in different programming languages, which can avoid the overhead of unnecessary repeated allocation of objects.

Unique referred to [go4.org/intern] (https://github.com/go4org/intern), moved it to the official library, and made corresponding changes. Issue #62483

As described by the official documentation, the unique package provides a lightweight (only eight bytes) implementation of comparing two variables for equality. For example, in the following code:

The performance improvement is still obvious

➜  unique git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test -bench='BenchmarkMake1' -count=5  
 goos: darwin 
 goarch: arm64 
 pkg: unique 
 cpu: Apple M1 Pro 
 BenchmarkMake1-10       122033748                9.692 ns/op 
 BenchmarkMake1-10       123878858                9.688 ns/op 
 BenchmarkMake1-10       123927121                9.706 ns/op 
 BenchmarkMake1-10       123849468                9.759 ns/op 
 BenchmarkMake1-10       123306187                9.673 ns/op 
 PASS 
 ok      unique  11.055s 
 ➜  unique git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test -bench='BenchmarkMake2' -count=5 
 goos: darwin 
 goarch: arm64 
 pkg: unique 
 cpu: Apple M1 Pro 
 BenchmarkMake2-10       1000000000               0.3118 ns/op 
 BenchmarkMake2-10       1000000000               0.3114 ns/op 
 BenchmarkMake2-10       1000000000               0.3119 ns/op 
 BenchmarkMake2-10       1000000000               0.3136 ns/op 
 BenchmarkMake2-10       1000000000               0.3115 ns/op 
 PASS 
 ok      unique  1.875s

However, you shouldn’t treat it as a global variable to use, store shared data, the unique underlying implementation is actually a map, and the cost of querying is also very high.
example

➜  huizhou92_test git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test --bench=BenchmarkBusinessUnique --count=5  
 goos: darwin 
 goarch: arm64 
 pkg: huizhou92_test 
 cpu: Apple M1 Pro 
 BenchmarkBusinessUnique-10          3114            373867 ns/op 
 BenchmarkBusinessUnique-10          3280            390818 ns/op 
 BenchmarkBusinessUnique-10          2941            376503 ns/op 
 BenchmarkBusinessUnique-10          3291            389665 ns/op 
 BenchmarkBusinessUnique-10          2954            398610 ns/op 
 PASS 
 ok      huizhou92_test  6.320s 
 ➜  huizhou92_test git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test --bench=BenchmarkBusinessString --count=5  
 goos: darwin 
 goarch: arm64 
 pkg: huizhou92_test 
 cpu: Apple M1 Pro 
 BenchmarkBusinessString-10      526721706                2.185 ns/op 
 BenchmarkBusinessString-10      548612287                2.183 ns/op 
 BenchmarkBusinessString-10      549425077                2.188 ns/op 
 BenchmarkBusinessString-10      549012100                2.182 ns/op 
 BenchmarkBusinessString-10      548929644                2.183 ns/op 
 PASS 
 ok      huizhou92_test  7.237s

Because of this, there is ongoing discussion regarding the usage of the unique package, possibly due to its infrequent usage. Regardless, the fact that this new package has been added to the standard library remains true. For instance, the net/netip package has already been refactored using unique to compare detailed information about IP addresses.