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
This article is first published in the medium MPP plan. If you are a medium user, please follow me in medium. Thank you very much.
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, 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
➜ 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
➜ 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, the discussion about unique is still ongoing, possibly because it is not used very often? Anyway, the fact that this new package has entered the standard library is a reality. net/netip has already been refactored using unique to compare detailed information about IP addresses.