This is one step towards optimizing WriteMsgUDPAddrPort.
Further steps remain, namely to avoid the syscall.Sockaddr interface,
as we do for UDPConn.WriteToUDP and UDPConn.ReadFromUDP.
A previous change optimized ReadMsgUDPAddrPort by having
ReadMsgUDP call ReadMsgUDPAddrPort rather than the other way around.
This change does not implement WriteMsgUDP in terms of WriteMsgUDPAddrPort,
because a few layers deep, on posix platforms only
(in ipToSockaddrInet4 and ipToSockaddrInet6),
is special handling of zero-length IP addresses and IPv4zero.
It treats IP(nil) as equivalent to 0.0.0.0 or ::,
and 0.0.0.0 as equivalent to :: in an IPv6 context.
Based on the comments, I suspect that this treatment was intended
for the Listen* API, not the Write* API, but it affects both,
and I am nervous about changing the behavior for Write*.
The netip package doesn't have a way to represent a "zero-length IP address"
as distinct from an invalid IP address (which is a good thing),
so to implement WriteMsgUDP using WriteMsgUDPAddrPort,
we would have to duplicate this special handling at the start of WriteMsgUDP.
But this handling depends on whether the UDPConn is an IPv4 or an IPv6 conn,
which is also platform-specific information.
As a result, every attempt I made to implement WriteMsgUDP using
WriteMsgUDPAddrPort while preserving behavior ended up
being considerably worse than copy/paste/modify.
This does mean that WriteMsgUDP and WriteMsgUDPAddrPort will have
different behavior in these cases.
name old time/op new time/op delta
ReadWriteMsgUDPAddrPort-8 5.29µs ± 6% 5.02µs ± 7% -5.14% (p=0.000 n=13+15)
name old alloc/op new alloc/op delta
ReadWriteMsgUDPAddrPort-8 128B ± 0% 64B ± 0% -50.00% (p=0.000 n=15+15)
name old allocs/op new allocs/op delta
ReadWriteMsgUDPAddrPort-8 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=15+15)