Hello everyone , I'm fried fish .
Writing this article is the first day of the new year , I originally wanted to say that it would be released this month Go1.18 了 . however , good heavens ,Go1.18 beta2 Released , The official informs the community Go1.18 To be dragged to 3 Month. , Cuckoo ...
Here's the picture :
So we still have to continue to learn new features , Today the fried fish will be combined Brad Fitzpatrick Written 《netaddr.IP: a new IP address type for Go》 Let's get to know Go1.18 New network library net/netip Reason .
background
The big man left
Original Go In the development team Brad Fitzpatrick, stay 2010~2020 All year round Go Team work , stay 2021 The company has changed since .
The following tweets :
The reason for leaving is : I have done the same thing for too long , A little bored , Don't want to fall into a comfortable dilemma .
Now it's time to change to Tailscale, do WireGuard Related work , Always deal with network libraries .
Demand is born
Written by big guy company Tailscale, It's essentially a web application , Deal with the Internet , Again Go Written , It will involve the standard library net
:
- In a single IP Use... In type
net.IP
. - Use on network presentation
net.IPNet
.
Sample code :
import (
"fmt"
"net"
)
func main() {
fmt.Println(net.IPv4(8, 8, 8, 8))
}
Output results :
8.8.8.8
Brad Fitzpatrick When actually writing and using , Find out net There are many problems with the type of standard library , It's not easy to use .
What's the problem now
Brad Fitzpatrick For the standard library net.IP The problem of , Listed directly in the article , The argument is full .
common 7 A big question :
- It's variable .
net.IP
The bottom type of is[]byte
, This means that anything you pass on to it can change it . - It is not comparable . because Go Medium slice It's not comparable , It means
net.IP
I won't support it Go Of==
Comparison of operators , Can not act as map Of key To use . - It has two kinds of IP Address type , To tangle with
net.IP
, stillnet.IPAddr
, It's annoying to choose . - It's big .Go Of
net.IP
contain 2 Parts of , Namely 24 Bytes of slice header and 4/6 Bytes of IP Address . If it isnet.IPAddr
It also includes Zone Field . - It allocates memory on the heap .Go Of net Packages are distributed everywhere , Put more work on GC On .
- It cannot be parsed . Parse from string form IP when ,Go Of IP Type cannot be distinguished IPv4 The mapping of IPv6 Address and IPv4 Address .
- It is transparent (transparent type),
net.IP
Is defined as :type IP []byte
, Is its public API Part of , Non modifiable .
Brad It was also mentioned that some of them were early designs , I was inexperienced at the time , Or did not consider well .
Now limited by Go1 Compatibility promise , It can't be changed ( Compatibility guarantee double-edged sword ?).
This is a real version “Eating your own dog food”, So in Tailscale He made another wheel inetaf/netaddr, Want to contribute , Put it into the standard library .
What you want in the future
The comparison table is as follows :
characteristic | Old scheme net.IP | New scheme |
---|---|---|
constant | , slice | |
Comparable | , slice | |
Small footprint | ,28~56 byte | , Fix 24 byte |
Do not allocate on the heap | ||
Support IPv4 and IPv6 | ||
distinguish IPv4 and IPv6 | ||
Support IPv6 Area | ||
Opaque type | ||
Interworking with the standard library | , Adaptation method required |
What you want , It's actually Brad Demands from business practice , Is to support the above mentioned 7 spot .
Solution
Current progress
The result of implementation , That is, the new plan has been made , He is inetaf/netaddr This library ( Of course , It does not rule out that it is the result inversion theory ). And in Go issues To initiate issues and proposal.
Russ Cox Initiated a discussion on the new proposal 《proposal: net/netaddr: add new IP address type, netaddr package (discussion)")》, And be accepted , Into the Go1.18 Among the new features of .
Remanufacture process
new net/netip
Every consideration point of the Library ,Brad Are explained in detail in the article .
Limited by length , Let's share two of them , Interested friends can read the analysis part of the original .
Interface type combination
In the matter of comparability ,Go The interface of (interface) Actually, it supports comparison , That is to say, it can be used as map Of key Conduct ==
Operator comparison .
The first version of the following scheme is implemented , Designed a new netaddr.IP
type :
type IP struct {
ipImpl
}
type ipImpl interface {
is4() bool
is6() bool
String() string
}
type v4Addr [4]byte
type v6Addr [16]byte
type v6AddrZone struct {
v6Addr
zone string
}
The above code , stay IP Added in the structure ipImpl Interface , It can support comparison , You can also avoid exposure ( Opaque type ), And can support IPv6.
The new problem is , Although it is more original net The small , But I still haven't achieved my goal , There is still the disadvantage of allocating on the heap .
Free of distribution 24 byte
If you continue to use the interface , Is unable to solve the fundamental goal (Brad The goal is 24 byte ) Of .
Because of the interface (interface) Occupy 16 byte , The remaining 8 Bytes can be used , Put the following things :
- Address family (v4、v6, Or neither , Such as :IP Zero value of ), Need at least 2 position .
- IPv6 Of zone Information .
We should also be able to compare , Obviously, the interface cannot be implemented , Because address +zone Information count bytes , Display is not enough .
There is no way to be formal and explicit ,Brad Thought of using packaging :
type IP struct {
addr [16]byte
zoneAndFamily uint64
}
But to do so , Means zoneAndFamily The number of digits in the field needs to be calculated , Then push the corresponding value accordingly , But it may not be too much trouble .
Final Brad Think of the , You can use pointers :
type IP struct {
addr [16]byte
zoneAndFamily *T
}
Redefine 3 The corresponding sentinel values are applied :
var (
z0 *intern.Value // Indicates a zero value .
z4 = new(intern.Value) // Express IPv4 Sentinel value of
z6noz = new(intern.Value) // Express IPv6 Sentinel value of ( No, zone).
)
So we can take IP The type is fixed in 24 byte .
summary
This network address Library , Generally, they are used less . however Brad Fitzpatrick A lot of energy and research have been invested here , Achieved the ultimate goal .
In addition to the functions of the Library , There are many technical optimization points worthy of our study and reference , Interested in further optimization , You can read :https://tailscale.com/blog/netaddr-new-ip-type-for-go/
This article introduces the new net/netip The library will be in Go1.18 As a new feature , Welcome to study and exchange together :)
If you have any questions, you are welcome to feedback and exchange in the comments area , The best relationship is mutual achievement , Everyone give the thumbs-up Namely Fried fish The greatest power of creation , Thank you for your support .
Articles are constantly updated , You can search through wechat 【 I have fried fish in my head 】 read , this paper GitHubgithub.com/eddycjy/blog Included , Study Go Language can be seen Go Learn maps and routes , welcome Star Hurry up .