That's not a language-specific thing, but is actually part of the IPv6 RFCs as IPv4-mapped IPv6 addresses: [1], [2]
This is super useful because (at least on Linux) IPv6 sockets per default are dual-stack and bind to both IPv6 and IPv6 (except if you are using the IPV6_V6ONLY sockopt or a sysctl), so you don't need to open and handle IPv4 and IPv6 sockets separately (well, maybe some extra code for logging/checking properly with the actual IPv4 address).
That is also documented in ipv6(7):
IPv4 connections can be handled with the v6 API by using
v4-mapped-on-v6 address type; thus a program needs to support only
this API type to support both protocols. This is handled
transparently by the address handling functions in the C library.
IPv4 and IPv6 share the local port space. When you get an IPv4
connection or packet to an IPv6 socket, its source address will be
mapped to v6.
[0]:
https://datatracker.ietf.org/doc/html/rfc5156#section-2.2
[1]:
https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5....