-Pakets von net/netip
Go-Sprache: Addr
Typ
Hallo zusammen! Heute werden wir uns mit dem net/netip
-Paket der Go-Sprache befassen und uns dabei auf den Typ Addr
konzentrieren. Wenn Sie mit dem Netzwerkcode von Go gearbeitet haben, sind Sie möglicherweise auf den alten Typ net.IP
gestoßen. Obwohl es uns gute Dienste geleistet hat, weist es einige Nachteile auf, die es für modernen Netzwerkcode weniger geeignet machen. Das net/netip
-Paket (eingeführt in Go 1.18) bietet uns eine leistungsfähigere und effizientere Möglichkeit, IP-Adressen zu verarbeiten.
net/netip.Addr
? Bevor wir auf die Details eingehen, wollen wir verstehen, warum es diesen Typ gibt. Der traditionelle net.IP
-Typ ist im Grunde ein Byte-Slice ([]byte
), was bedeutet:
==
-Operator kann nicht zum Vergleich verwendet werdenDer neue Addr
Typ löst all diese Probleme. Es ist ein Werttyp (interne Struktur), unveränderlich und stellt immer eine gültige IP-Adresse dar. Keine defensive Programmierung mehr!
Addr
Sehen wir uns die Grundlagen der Erstellung und Verwendung von Addr
an:
<code class="language-go">package main import ( "fmt" "net/netip" ) func main() { // 从字符串创建Addr addr, err := netip.ParseAddr("192.168.1.1") if err != nil { panic(err) } // 如果你绝对确定输入 addr2 := netip.MustParseAddr("2001:db8::1") fmt.Printf("IPv4: %v\nIPv6: %v\n", addr, addr2) }</code>
ParseAddr
ist, dass es sehr streng ist. Es werden keine seltsamen Formate oder ungültigen Adressen akzeptiert. Zum Beispiel:
<code class="language-go">// 这些将会失败 _, err1 := netip.ParseAddr("256.1.2.3") // 无效的IPv4八位字节 _, err2 := netip.ParseAddr("2001:db8::1::2") // 无效的IPv6(双冒号) _, err3 := netip.ParseAddr("192.168.1.1/24") // Addr不允许CIDR表示法</code>
Addr
MethodeLassen Sie uns die wichtigsten Methoden erkunden, die Sie mit Addr
verwenden werden. Ich werde einige praktische Beispiele dafür geben, wo jede Methode nützlich ist.
<code class="language-go">func checkAddressType(addr netip.Addr) { if addr.Is4() { fmt.Println("这是IPv4") // 你可以在这里安全地使用As4() bytes := addr.As4() fmt.Printf("作为字节:%v\n", bytes) } else if addr.Is6() { fmt.Println("这是IPv6") // 你可以在这里安全地使用As16() bytes := addr.As16() fmt.Printf("作为字节:%v\n", bytes) } }</code>
Profi-Tipp: Wenn Sie mit IPv4-zugeordneten IPv6-Adressen (z. B. ::ffff:192.0.2.1
) arbeiten, verwenden Sie Is4In6()
, um diese zu erkennen. Dies ist besonders nützlich, wenn Sie protokollunabhängigen Code schreiben.
Addr
bietet mehrere Möglichkeiten zur Klassifizierung von IP-Adressen. Hier ist ein umfassendes Beispiel:
<code class="language-go">func classifyAddress(addr netip.Addr) { checks := []struct { name string fn func() bool }{ {"IsGlobalUnicast", addr.IsGlobalUnicast}, {"IsPrivate", addr.IsPrivate}, {"IsLoopback", addr.IsLoopback}, {"IsMulticast", addr.IsMulticast}, {"IsLinkLocalUnicast", addr.IsLinkLocalUnicast}, {"IsLinkLocalMulticast", addr.IsLinkLocalMulticast}, {"IsInterfaceLocalMulticast", addr.IsInterfaceLocalMulticast}, {"IsUnspecified", addr.IsUnspecified}, } for _, check := range checks { if check.fn() { fmt.Printf("地址是 %s\n", check.name) } } }</code>
Praxisbeispiel: Nehmen wir an, Sie schreiben einen Dienst, der an alle Schnittstellen außer der Loopback-Schnittstelle gebunden werden muss:
<code class="language-go">func getBindableAddresses(addrs []netip.Addr) []netip.Addr { var bindable []netip.Addr for _, addr := range addrs { if !addr.IsLoopback() && !addr.IsLinkLocalUnicast() { bindable = append(bindable, addr) } } return bindable }</code>
Wenn Sie IPv6 verwenden, werden Sie irgendwann auf Zonen stoßen. Sie werden hauptsächlich mit Link-Local-Adressen verwendet, um anzugeben, welche Netzwerkschnittstelle verwendet werden soll:
<code class="language-go">func handleZones() { // 创建一个带有区域的地址 addr := netip.MustParseAddr("fe80::1%eth0") // 获取区域 zone := addr.Zone() fmt.Printf("区域:%s\n", zone) // 比较带有区域的地址 addr1 := netip.MustParseAddr("fe80::1%eth0") addr2 := netip.MustParseAddr("fe80::1%eth1") // 由于区域不同,这些是不同的地址 fmt.Printf("相同的地址?%v\n", addr1 == addr2) // false // WithZone创建一个具有不同区域的新地址 addr3 := addr1.WithZone("eth2") fmt.Printf("新的区域:%s\n", addr3.Zone()) }</code>
Lassen Sie uns das alles in einem praktischen Beispiel zusammenfassen. Dies ist ein einfacher IP-Filter, der für Webdienste verwendet werden kann:
<code class="language-go">type IPFilter struct { allowed []netip.Addr denied []netip.Addr } func NewIPFilter(allowed, denied []string) (*IPFilter, error) { f := &IPFilter{} // 解析允许的地址 for _, a := range allowed { addr, err := netip.ParseAddr(a) if err != nil { return nil, fmt.Errorf("无效的允许地址 %s: %w", a, err) } f.allowed = append(f.allowed, addr) } // 解析拒绝的地址 for _, d := range denied { addr, err := netip.ParseAddr(d) if err != nil { return nil, fmt.Errorf("无效的拒绝地址 %s: %w", d, err) } f.denied = append(f.denied, addr) } return f, nil } func (f *IPFilter) IsAllowed(ip string) bool { addr, err := netip.ParseAddr(ip) if err != nil { return false } // 首先检查拒绝列表 for _, denied := range f.denied { if addr == denied { return false } } // 如果没有指定允许的地址,则允许所有未被拒绝的地址 if len(f.allowed) == 0 { return true } // 检查允许列表 for _, allowed := range f.allowed { if addr == allowed { return true } } return false }</code>
Anwendungsbeispiel:
<code class="language-go">func main() { filter, err := NewIPFilter( []string{"192.168.1.100", "10.0.0.1"}, []string{"192.168.1.50"}, ) if err != nil { panic(err) } tests := []string{ "192.168.1.100", // 允许 "192.168.1.50", // 拒绝 "192.168.1.200", // 不在任何列表中 } for _, ip := range tests { fmt.Printf("%s 允许?%v\n", ip, filter.IsAllowed(ip)) } }</code>
net/netip.Addr
sind seine Leistungsmerkmale. Da es sich um einen Werttyp handelt:
net.IP
, wo ein Nullwert gültig sein kann)net.IP
und netip.Addr
nicht willkürlich. Aus Gründen der Konsistenz sollten Sie jedoch versuchen, netip.Addr
in Ihrer gesamten Codebasis beizubehalten. MustParseAddr
Obwohl dies im Test- oder Initialisierungscode praktisch ist, bevorzugen Sie ParseAddr
im Produktionscode, der Benutzereingaben verarbeitet. WithZone
), geben tatsächlich eine neue Adresse zurück. Dieser Artikel behandelt die Grundlagen und einige fortgeschrittene Verwendungsmöglichkeiten der Addr
-Typen, aber im net/netip
-Paket gibt es noch viel mehr zu entdecken. Im nächsten Artikel schauen wir uns AddrPort
an, das eine IP-Adresse mit einer Portnummer kombiniert – sehr nützlich für die Netzwerkprogrammierung.
Bis dahin viel Spaß beim Programmieren! Wenn Sie Fragen zur Verwendung von net/netip.Addr
in Ihrem Projekt haben, können Sie sich gerne an uns wenden.
Das obige ist der detaillierte Inhalt vonDen Netz-/Netip-Addr-Typ von Go verstehen: Ein tiefer Einblick. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!