Maison >développement back-end >Golang >Comprendre le type d'adresse Go's net/netip : une plongée en profondeur
Go Language : net/netip
typeAddr
du langage Go, en nous concentrant sur le type net/netip
. Si vous avez travaillé avec le code réseau de Go, vous avez peut-être rencontré l'ancien type Addr
. Bien qu'il nous ait bien servi, il présente certains inconvénients qui le rendent moins adapté au code réseau moderne. Le package net.IP
(introduit dans Go 1.18) nous offre un moyen plus puissant et efficace de gérer les adresses IP. net/netip
net/netip.Addr
est essentiellement une tranche d'octets (net.IP
), ce qui signifie : []byte
==
résout tous ces problèmes. C'est un type valeur (structure interne), immuable, et représente toujours une adresse IP valide. Fini la programmation défensive ! Addr
Addr
: Addr
<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>
est qu'il est très strict. Il n'acceptera pas les formats étranges ou les adresses invalides. Par exemple : ParseAddr
<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>Discuter en profondeur de la
Addr
. Je vais partager quelques exemples pratiques montrant où chaque méthode est utile. Addr
<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>Conseil de pro : lorsque vous traitez des adresses IPv6 mappées IPv4 (telles que
), utilisez ::ffff:192.0.2.1
pour les détecter. Ceci est particulièrement utile lors de l’écriture de code indépendant du protocole. Is4In6()
propose plusieurs façons de classer les adresses IP. Voici un exemple complet : Addr
<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>Exemple pratique : disons que vous écrivez un service qui doit se lier à toutes les interfaces à l'exception de l'interface de bouclage :
<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>Utiliser la zone (ID de portée IPv6)
<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>Application pratique : Filtre d'adresse IP
<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>Exemple d'utilisation :
<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>Notes de performances
réside dans ses fonctionnalités de performance. Puisqu'il s'agit d'un type valeur : net/netip.Addr
net.IP
, où une valeur zéro peut être valide)net.IP
et netip.Addr
au hasard Bien qu'il soit possible de convertir entre eux, par souci de cohérence, essayez de vous en tenir à netip.Addr
dans toute votre base de code. MustParseAddr
Bien que pratique dans le code de test ou d'initialisation, préférez ParseAddr
dans le code de production qui gère les entrées de l'utilisateur. WithZone
) renvoient en fait une nouvelle adresse. Cet article couvre les bases et une utilisation avancée des types Addr
, mais il y a bien plus à explorer dans le package net/netip
. Dans le prochain article, nous examinerons AddrPort
, qui combine une adresse IP avec un numéro de port - très utile pour la programmation réseau.
En attendant, bon codage ! Si vous avez des questions sur l'utilisation de net/netip.Addr
dans votre projet, n'hésitez pas à nous contacter.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!