ホームページ > バックエンド開発 > Golang > Go の net/netip アドレス タイプについて: 詳細

Go の net/netip アドレス タイプについて: 詳細

Susan Sarandon
リリース: 2025-01-11 10:55:42
オリジナル
976 人が閲覧しました

Understanding Go

Go 言語の net/netip パッケージの詳細な説明: Addrtype

皆さん、こんにちは!今日は、net/netip 型に焦点を当てて、Go 言語の Addr パッケージについて詳しく説明します。 Go のネットワーク コードを使用している場合は、古い net.IP タイプに遭遇したことがあるかもしれません。これは私たちにとって有益ですが、最新のネットワーク コードには適さないといういくつかの欠点があります。 net/netip パッケージ (Go 1.18 で導入) は、IP アドレスを処理するためのより強力かつ効率的な方法を提供します。

なぜnet/netip.Addrを選ぶのですか?

詳細に入る前に、このタイプが存在する理由を理解しましょう。従来の net.IP 型は基本的にバイトのスライス ([]byte) であり、次のことを意味します:

  • 変数
  • ヒープ割り当てが必要です
  • 無効なステータスが含まれている可能性があります
  • 比較に == 演算子は使用できません

新しい Addr タイプは、これらの問題をすべて解決します。これは値型 (内部構造) であり、不変であり、常に有効な IP アドレスを表します。もう防御的なプログラミングは必要ありません。

始めましょう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>
ログイン後にコピー

ParseAddr の利点の 1 つは、非常に厳密であることです。奇妙な形式や無効なアドレスは受け入れられません。例:

<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方法

について詳しく話し合う

Addr で使用する主なメソッドを見てみましょう。それぞれの方法が役立つ例をいくつか紹介します。

これは IPv4 ですか、それとも 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>
ログイン後にコピー

プロのヒント: IPv4 にマップされた IPv6 アドレス (::ffff:192.0.2.1 など) を扱う場合は、Is4In6() を使用して検出します。これは、プロトコルに依存しないコードを作成する場合に特に便利です。

住所の分類方法

Addr タイプは、IP アドレスを分類するいくつかの方法を提供します。包括的な例を次に示します:

<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>
ログイン後にコピー

実践例: ループバック インターフェイスを除くすべてのインターフェイスにバインドする必要があるサービスを作成しているとします。

<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>
ログイン後にコピー

使用ゾーン (IPv6 スコープ ID)

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>
ログイン後にコピー

実際の応用: IP アドレスフィルター

これらすべてを実際の例にまとめてみましょう。これは、Web サービスに使用できる単純な 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>
ログイン後にコピー

使用例:

<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 の優れた点の 1 つは、そのパフォーマンス機能です。値型なので:

  • ヒープ割り当てを行わない基本操作
  • 効率的な比較演算
  • ゼロ値は無効です (ゼロ値が有効な可能性がある net.IP とは異なります)

よくある落とし穴とトリック

  1. net.IPnetip.Addr をランダムに混合しないでください。これらの間で変換することは可能ですが、一貫性を保つために、コードベース全体で netip.Addr を使用するようにしてください。
  2. 比較の領域に注意してください 領域に加えて、2 つの同一のアドレスは異なるアドレスとみなされます。
  3. 使用には注意してください MustParseAddr テストまたは初期化コードでは便利ですが、ユーザー入力を処理する運用コードでは ParseAddr を使用することを推奨します。
  4. 不変であることを覚えておいてください アドレスを変更するように見えるすべてのメソッド (WithZone など) は、実際には新しいアドレスを返します。

次は何ですか?

この記事では、Addr 型の基本といくつかの高度な使用法について説明しますが、net/netip パッケージにはさらに多くの内容が含まれています。次の記事では、IP アドレスとポート番号を組み合わせる AddrPort について説明します。これはネットワーク プログラミングに非常に便利です。

それまではコーディングを楽しんでください!プロジェクトで net/netip.Addr を使用してご質問がある場合は、お気軽にお問い合わせください。

以上がGo の net/netip アドレス タイプについて: 詳細の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート