go: net/netip: missing odds and ends for 1.18 [freeze exception]
Now that netip has landed, I’ve started porting code to it. I’m hoping to get a bit of experience doing this before Go 1.18 in order to catch issues before it ships. So far I’ve identified six things that are missing, which I was hoping we could get into Go 1.18, as a followup to #46518.
Items with ⏳ have CLs still pending, and items with ✅ have CLs that have been submitted.
1. MarshalBinary
/UnmarshalBinary
on AddrPort
and Prefix
✅
Addr.MarshalBinary
and Addr.UnmarshalBinary
both exist. However, the same is not true for the remaining two types, AddrPort
and Prefix
. This makes it very hard to use with encoding/gob
, because not only are these marshals missing, but the inner addr + port/cidr members are unexported. So, I propose adding these two methods, with implementations that simply concatenate Addr.MarshalBinary
output with little-endian encoding of the port (uint16
) for AddrPort
or cidr (uint8
) for Prefix
.
2. Addr.AsSlice
✅
There is netip.AddrFromSlice()
and netip.AddrFrom4
, but there is only netip.As4
and no netip.AsSlice
. This may seem kind of trifling, but it winds up being kind of annoying when coding things; I find myself writing a lot of:
var s []byte
if addr.Is4() {
arr := addr.As4()
s = arr[:]
} else addr.Is16() {
arr := addr.As16()
s = arr[:]
}
You can’t slice an rvalue, so that temporary is needed. And sometimes I just want a slice, regardless of what kind of IP it is, and having to open code dispatch for that every time is a bit of a pain. The above snippet would be simplified to:
s := addr.AsSlice()
3. IPv4Unspecified()
✅
There is IPv6Unspecified()
, but not IPv4Unspecified()
. This is sort of confusing, and code would be more clear and consistent if I could write netip.IPv4Unspecified()
instead of netip.AddrFrom4([4]byte{})
.
4. One remaining allocation in UDP path
The “net” package has one remaining allocation in the UDP packet path, which @josharian has a change to fix, so that UDP sends/receives can be allocation-free. Being alloc-free is one of the original motivations behind netip
in the first place.
5. Missing UDPAddr
and TCPAddr
analogs ❌ (partially accepted, partially punted to go 1.19)
We have ReadFromUDPAddrPort
and such, for reads and writes of UDP and TCP sockets, but the listener/dialer functions still take the old TCPAddr
and UDPAddr
structs. So, we’ll need new functions there, to avoid unwanted type conversions by users.
6. AddrFromSlice
should return only one value ❌ (rejected)
The AddrFrom4
and AddrFrom6
functions never fail, and that makes it easy to pass them around with function composition. AddrFromSlice
, however, awkwardly returns an ok
value. But, when ok==false
, the returned Addr
isn’t valid anyway. So folks who want to check for validity can just do addr.IsValid()
like normal, instead of having to learn something new and odd. So, we should drop the ok
return value, especially as most users already ignore it.
(I’ll update this issue if I find anything new.)
CC @bradfitz @crawshaw @josharian @danderson @ianlancetaylor
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 23 (14 by maintainers)
Commits related to this issue
- net/netip: add Addr.AsSlice() method We have AddrFrom4, AddrFrom6, AddrFromSlice and As4, As6, but we are missing AsSlice, so this commit adds the missing function. It also gets rid of the less ergon... — committed to golang/go by zx2c4 3 years ago
- net/netip: add missing encoding.BinaryUnmarshaler to AddrPort and Prefix The Addr type got an encoding.BinaryUnmarshaler implementation, but not AddrPort and Prefix. This commit adds the missing impl... — committed to golang/go by zx2c4 3 years ago
- net/netip: add IPv4Unspecified There is IPv6Unspecified but there is not IPv4Unspecified, making for inconsistent code. This commit adds the missing function. Updates #49298. Change-Id: Id2519b6463... — committed to golang/go by zx2c4 3 years ago
- net: add conversion from AddrPort to TCPAddr to complement existing inverse We already have various member functions of TCPAddr that return an AddrPort, but we don't have a helper function to go from... — committed to golang/go by zx2c4 3 years ago
(psst, I think you may have meant to tag @danderson instead of me. 😃
Maybe we can drop
IPAddrParts()
? the discoverability ofAsSlice()
is better and there’s already aZone()
.MarshalBinary()
also encodes the zone, so it’s something differentCC @golang/release
One thing I was hoping to reach some consensus about was item 6:
6.
AddrFromSlice
should return only one value ⏳The
AddrFrom4
andAddrFrom6
functions never fail, and that makes it easy to pass them around with function composition.AddrFromSlice
, however, awkwardly returns anok
value. But, whenok==false
, the returnedAddr
isn’t valid anyway. So folks who want to check for validity can just doaddr.IsValid()
like normal, instead of having to learn something new and odd. So, we should drop theok
return value, especially as most users already ignore it.Brad mentioned in the issue that forcing people to check the
ok
value was a feature, not a bug. I see it differently, as a nuisance. Thought I should ask here how others feel, or if I should abandon that CL. (The CL’s diff shows the simplification in other parts of the code afforded by this improvement.)Also, @josharian has a change to remove the remaining 1 alloc in the UDP paths so UDP sends/receives can be allocation-free, which is the main motivation of netip in the first place. It’d be a better story if the package & its benefit came together in the same release, rather than waiting for Go 1.19 to make use of netip in net be zero-alloc.
In the same spirit of the #49073 freeze exception proposal, this is a proposal that we finish the misc loose ends on netip for 1.18.