Go language net/netip
: Addr
taip
Hello semua! Hari ini kita akan menyelidiki pakej net/netip
bahasa Go, memfokuskan pada jenis Addr
. Jika anda telah menggunakan kod rangkaian Go, anda mungkin pernah menemui jenis net.IP
lama. Walaupun ia telah memberi manfaat kepada kami, ia mempunyai beberapa kelemahan yang menjadikannya kurang sesuai untuk kod rangkaian moden. Pakej net/netip
(diperkenalkan dalam Go 1.18) memberi kita cara yang lebih berkuasa dan cekap untuk mengendalikan alamat IP.
net/netip.Addr
? Sebelum kita masuk ke butiran, mari kita fahami sebab jenis ini wujud. Jenis net.IP
tradisional pada asasnya ialah sekeping bait ([]byte
), yang bermaksud:
==
untuk perbandinganJenis Addr
baharu menyelesaikan semua masalah ini. Ia ialah jenis nilai (struktur dalaman), tidak boleh diubah, dan sentiasa mewakili alamat IP yang sah. Tiada lagi pengaturcaraan defensif!
Addr
Mari kita lihat asas mencipta dan menggunakan 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>
ParseAddr
ialah ia sangat ketat. Ia tidak akan menerima format pelik atau alamat tidak sah. Contohnya:
<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
kaedahMari teroka kaedah utama yang akan anda gunakan dengan Addr
. Saya akan berkongsi beberapa contoh praktikal di mana setiap kaedah berguna.
<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>
Petua Pro: Apabila berurusan dengan alamat IPv6 dipetakan IPv4 (seperti ::ffff:192.0.2.1
), gunakan Is4In6()
untuk mengesannya. Ini amat berguna apabila menulis kod protokol-agnostik.
Addr
menyediakan beberapa cara untuk mengklasifikasikan alamat IP. Berikut ialah contoh menyeluruh:
<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>
Contoh praktikal: Katakan anda sedang menulis perkhidmatan yang perlu terikat pada semua antara muka kecuali antara muka gelung balik:
<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>
Jika anda menggunakan IPv6, anda akhirnya akan menghadapi zon. Ia digunakan terutamanya dengan alamat pautan-tempatan untuk menentukan antara muka rangkaian yang hendak digunakan:
<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>
Mari kita letakkan semua ini dalam contoh praktikal. Ini ialah penapis IP mudah yang boleh digunakan untuk perkhidmatan web:
<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>
Contoh penggunaan:
<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
ialah ciri prestasinya. Memandangkan ia adalah jenis nilai:
net.IP
, di mana nilai sifar mungkin sah)net.IP
dan netip.Addr
secara rawak Walaupun anda boleh menukar antara keduanya, demi ketekalan, cuba kekalkan dengan netip.Addr
di seluruh pangkalan kod anda. MustParseAddr
Walaupun mudah dalam ujian atau kod permulaan, pilih ParseAddr
dalam kod pengeluaran yang mengendalikan input pengguna. WithZone
) sebenarnya mengembalikan alamat baharu. Artikel ini merangkumi perkara asas dan beberapa penggunaan lanjutan bagi jenis Addr
, tetapi banyak lagi yang perlu diterokai dalam pakej net/netip
. Dalam artikel seterusnya, kita akan melihat AddrPort
, yang menggabungkan alamat IP dengan nombor port - sangat berguna untuk pengaturcaraan rangkaian.
Sehingga itu, selamat mengekod! Jika anda mempunyai sebarang soalan menggunakan net/netip.Addr
dalam projek anda, sila hubungi kami.
Atas ialah kandungan terperinci Memahami Jenis Addr Go's net/netip: A Deep Dive. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!