Go 언어의 net/netip
패키지에 대한 자세한 설명: Addr
type
안녕하세요 여러분! 오늘은 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
의 장점 중 하나는 매우 엄격하다는 것입니다. 이상한 형식이나 유효하지 않은 주소는 허용되지 않습니다. 예:
<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
에서 사용할 주요 방법을 살펴보겠습니다. 각 방법이 유용한 몇 가지 실제 사례를 공유하겠습니다.
<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를 사용하는 경우 결국에는 영역에 직면하게 됩니다. 주로 링크 로컬 주소와 함께 사용하여 사용할 네트워크 인터페이스를 지정합니다.
<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 필터입니다.
<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
의 가장 큰 장점 중 하나는 바로 성능입니다. 값 유형이므로:
net.IP
과 다름)net.IP
과 netip.Addr
을 무작위로 혼합하지 마세요. 둘 사이를 변환하는 것은 가능하지만 일관성을 위해 코드 베이스 전체에서 netip.Addr
를 고수하도록 하세요. MustParseAddr
테스트나 초기화 코드에서는 편리하지만 사용자 입력을 처리하는 프로덕션 코드에서는 ParseAddr
을 선호합니다. WithZone
)는 실제로 새 주소를 반환합니다. 이 문서에서는 Addr
유형의 기본 사항과 일부 고급 사용법을 다루지만 net/netip
패키지에는 더 많은 내용을 살펴볼 수 있습니다. 다음 기사에서는 IP 주소와 포트 번호를 결합하는 AddrPort
을 살펴보겠습니다. 이는 네트워크 프로그래밍에 매우 유용합니다.
그때까지 즐거운 코딩하세요! 프로젝트에 net/netip.Addr
을 사용하면서 궁금한 점이 있으면 언제든지 문의해 주세요.
위 내용은 Gos net/netip Addr 유형 이해: 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!