Rumah > pembangunan bahagian belakang > Golang > Memahami Jenis Addr Go's net/netip: A Deep Dive

Memahami Jenis Addr Go's net/netip: A Deep Dive

Susan Sarandon
Lepaskan: 2025-01-11 10:55:42
asal
940 orang telah melayarinya

Understanding Go

Penjelasan terperinci tentang pakej

Go language net/netip: Addrtaip

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.

Mengapa memilihnet/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:

  • Pembolehubah
  • Memerlukan peruntukan timbunan
  • Mungkin mengandungi status tidak sah
  • Tidak boleh menggunakan operator == untuk perbandingan

Jenis 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!

MulakanAddr

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>
Salin selepas log masuk
Satu kelebihan

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>
Salin selepas log masuk

Bincangkan secara mendalam Addrkaedah

Mari teroka kaedah utama yang akan anda gunakan dengan Addr. Saya akan berkongsi beberapa contoh praktikal di mana setiap kaedah berguna.

Adakah ini IPv4 atau IPv6?

<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>
Salin selepas log masuk

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.

Kaedah pengelasan alamat

Jenis

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>
Salin selepas log masuk

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>
Salin selepas log masuk

Gunakan zon (ID skop IPv6)

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>
Salin selepas log masuk

Aplikasi Praktikal: Penapis Alamat IP

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>
Salin selepas log masuk

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>
Salin selepas log masuk

Nota Prestasi

Salah satu perkara hebat tentang

net/netip.Addr ialah ciri prestasinya. Memandangkan ia adalah jenis nilai:

  • Operasi asas tanpa peruntukan timbunan
  • Operasi perbandingan yang cekap
  • Nilai sifar adalah tidak sah (tidak seperti net.IP, di mana nilai sifar mungkin sah)

Beberapa perangkap dan muslihat biasa

  1. Jangan campurkan 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.
  2. Perhatikan kawasan dalam perbandingan Selain kawasan itu, dua alamat yang sama dianggap sebagai alamat yang berbeza.
  3. Gunakan dengan berhati-hati MustParseAddr Walaupun mudah dalam ujian atau kod permulaan, pilih ParseAddr dalam kod pengeluaran yang mengendalikan input pengguna.
  4. Ingat ia tidak boleh diubah Semua kaedah yang kelihatan untuk mengubah suai alamat (seperti WithZone) sebenarnya mengembalikan alamat baharu.

Apa yang seterusnya?

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!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan