Blog IT, Blog Marketing

netaddr.IP - nowy typ IP w Go

netaddr.IP - nowy typ IP w Go

Marcin Sarna , 12.03.2021 r.

Przykład na to, że w języku programowania zawsze można coś ulepszyć.

Zapotrzebowanie

Pisząc aplikację sieciową zachodzi częsta konieczność pracy tak z pojedynczymi adresami IP jak i zestawami adresów IP a do tego dochodzi konieczność różnych manipulacji na tych danych. W języku Go służy do tego net.IP zawarty w bibliotece standardowej Go. Dla sieci można się zaś posłużyć net.IPNet. Tailsacle, dostawca usługi VPN, korzystający z Go, stwierdził jednak że domyślne rozwiązanie zawarte w tym języku programowania go nie zadowala. Napisali więc nowy pakiet inet.af/netaddr (dostępny na ich GitHubie) zawierający nowy typ dla adresu IP.

Co im się nie podobało w net.IP?

Na liście skarg, zażaleń i wniosku znalazły się m.in. następujące zarzuty względem net.IP:

  1. Jest to typ mutujący. Podstawowy typ net.IP to po prostu byte[] co oznacza, że wszystko, do czego go przekażesz, może go zmodyfikować. Tymczasem niezmienne struktury danych są bezpieczniejsze i łatwiejsze w użyciu.
  2. Nie jest porównywalny, nie wspiera operatora == i nie może być używany jako klucz mapy.
  3. Jest duży. Adres IP w net.IP Go składa się z dwóch części: 24-bajtowego nagłówka segmentu, a także 4 lub 16 bajtów adresu IP. Jeśli chcesz mieć strefę IPv6, musisz użyć net.IPAddr z 16-bajtowym nagłówkiem.

Celem prac było więc przede wszystkim zapewnienie aby nowy typ był niemutowalny, porównywalny i zajmował możliwie mało pamięci.

Prace trwały

Tailscale zaczęło od:

type IP struct {
Addr [16]byte
}

Zapewnili niemutowalność, porównywalność i mały rozmiar ale nadal nie było rozróżnienia IPv4 od IPv6 i wsparcia stref IPv6. No i nie osiągnięto interoperacyjności ze standardową bibliotekę Go. Korzystając z tego, że interfejsy w tym języku są porównywalne, spróbowano z:

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
}

Lepiej ale nie idealnie – nadal brak było chociażby współpracy ze standard library.

Sprawdź oferty pracy na TeamQuest

Wskaźnik na ratunek

W końcu zdecydowano się użyć wskaźnika:

type IP struct {
addr [16]byte
zoneAndFamily *T
}

var (
z0 *T // nil for the zero value
z4 = new(T) // sentinel value to mean IPv4
z6 = new(T) // sentinel value to mean IPv6 with no zone
)

Ostatecznie powstał pakiet go4.org/intern zawierający całą brudną robotę (niejako backend tego nowego typu) tak aby pakiet inet.af/netaddr mógł wyglądać schludniej. Później były dalsze zmiany, np. zamiast addr [16]byte użyto parę wartości uint64. Obecnie inet.af/netaddr zawiera:

  • IPPort: typ wartości dla adresu IP i portu
  • IPPrefix: typ wartości dla adresu IP i prefiks CIDR (np. 192.168.0.1/16)
  • IPRange: typ wartości dla zakresu adresów IP (np. 10.0.0.200-100.0.0.255)
  • IPSet: wydajny, niezmienny zestaw adresów IP, zbudowany za pomocą IPSetBuilder.

Najnowsze oferty pracy:

Polecane wpisy na blogu IT:

Szukasz pracownika IT?

Dostarczymy Ci najlepszych specjalistów z branży IT. Wyślij zapytanie

Wyrażam zgodę TeamQuest Sp. z o.o. na przetwarzanie moich danych osobowych w celu marketingu produktów i usług własnych TeamQuest, w tym na kontaktowanie się ze mną w formie połączenia telefonicznego lub środkami elektronicznymi.
Administratorem podanych przez Ciebie danych osobowych jest TeamQuest Sp. z o.o., z siedzibą w Warszawie (00-814), ul. Miedziana 3a/21, zwana dalej „Administratorem".
Jeśli masz jakiekolwiek pytania odnośnie przetwarzania przez nas Twoich danych, skontaktuj się z naszym Inspektorem Ochrony Danych (IOD). Do Twojej dyspozycji jest pod adresem e-mail: office@teamquest.pl.
W jakim celu i na jakiej podstawie będziemy wykorzystywać Twoje dane? Dowiedz się więcej