Home >Backend Development >Golang >Working with AddrPort in net/netip: Complete Guide

Working with AddrPort in net/netip: Complete Guide

Patricia Arquette
Patricia ArquetteOriginal
2025-01-18 00:14:41524browse

Working with AddrPort in net/netip: Complete Guide

Continuing our exploration of the net/netip package, we now focus on AddrPort, a structure elegantly combining IP addresses and port numbers. This pairing is fundamental in network programming, crucial for web servers, database connections, and virtually any network service.

Why Use AddrPort?

Prior to net/netip, managing IP:port combinations often involved string manipulation, leading to parsing complexities and potential errors. AddrPort provides a streamlined, type-safe alternative.

Getting Started with AddrPort

Let's begin with the basics:

<code class="language-go">package main

import (
    "fmt"
    "net/netip"
)

func main() {
    // Create from a string
    ap1, err := netip.ParseAddrPort("192.168.1.1:8080")
    if err != nil {
        panic(err)
    }

    // Create from Addr and port
    addr := netip.MustParseAddr("192.168.1.1")
    ap2 := netip.AddrPortFrom(addr, 8080)

    fmt.Printf("From string: %v\nFrom components: %v\n", ap1, ap2)
}</code>

Key points regarding the port number:

  • Must be within the range 0-65535.
  • Stored as a uint16.
  • Leading zeros are permitted during parsing ("8080" and "08080" are equivalent).

Exploring AddrPort Methods

Let's examine the methods available for AddrPort and their applications.

Accessing Address and Port Components

<code class="language-go">func examineAddrPort(ap netip.AddrPort) {
    // Retrieve the address component
    addr := ap.Addr()
    fmt.Printf("Address: %v\n", addr)

    // Retrieve the port number
    port := ap.Port()
    fmt.Printf("Port: %d\n", port)

    // Obtain the string representation ("<addr>:<port>")
    str := ap.String()
    fmt.Printf("String representation: %s\n", str)
}</code>

Handling IPv4 and IPv6 Addresses

AddrPort seamlessly supports both IPv4 and IPv6:

<code class="language-go">func handleBothIPVersions() {
    // IPv4 with port
    ap4 := netip.MustParseAddrPort("192.168.1.1:80")

    // IPv6 with port
    ap6 := netip.MustParseAddrPort("[2001:db8::1]:80")

    // Note: Brackets are required for IPv6 addresses.  "2001:db8::1:80" would fail.

    // IPv6 with zone and port
    apZone := netip.MustParseAddrPort("[fe80::1%eth0]:80")

    fmt.Printf("IPv4: %v\n", ap4)
    fmt.Printf("IPv6: %v\n", ap6)
    fmt.Printf("IPv6 with zone: %v\n", apZone)
}</code>

Real-World Applications of AddrPort

Let's explore practical scenarios where AddrPort excels.

1. A Simple TCP Server

<code class="language-go">func runServer(ap netip.AddrPort) error {
    listener, err := net.Listen("tcp", ap.String())
    if err != nil {
        return fmt.Errorf("failed to start server: %w", err)
    }
    defer listener.Close()

    fmt.Printf("Server listening on %v\n", ap)

    for {
        conn, err := listener.Accept()
        if err != nil {
            return fmt.Errorf("accept failed: %w", err)
        }

        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()

    // Handle the connection...
}</code>

2. A Service Registry

This example demonstrates a service registry managing services and their endpoints:

<code class="language-go">// ... (ServiceRegistry struct and methods as in the original example) ...</code>

3. Load Balancer Configuration

Here's how AddrPort can be used in a load balancer configuration:

<code class="language-go">// ... (LoadBalancer struct and methods as in the original example) ...</code>

Common Patterns and Best Practices

  1. Input Validation: Always validate user-provided input:
<code class="language-go">func validateEndpoint(input string) error {
    _, err := netip.ParseAddrPort(input)
    if err != nil {
        return fmt.Errorf("invalid endpoint %q: %w", input, err)
    }
    return nil
}</code>
  1. Zero Value Handling: The zero value of AddrPort is invalid:
<code class="language-go">func isValidEndpoint(ap netip.AddrPort) bool {
    return ap.IsValid()
}</code>
  1. String Representation: When storing AddrPort as strings (e.g., in configuration files):
<code class="language-go">func saveConfig(endpoints []netip.AddrPort) map[string]string {
    config := make(map[string]string)
    for i, ep := range endpoints {
        key := fmt.Sprintf("endpoint_%d", i)
        config[key] = ep.String()
    }
    return config
}</code>

Integration with the Standard Library

AddrPort integrates seamlessly with the standard library:

<code class="language-go">func dialService(endpoint netip.AddrPort) (net.Conn, error) {
    return net.Dial("tcp", endpoint.String())
}

func listenAndServe(endpoint netip.AddrPort, handler http.Handler) error {
    return http.ListenAndServe(endpoint.String(), handler)
}</code>

Performance Considerations

  1. Prefer AddrPortFrom: When you already have a valid Addr, use AddrPortFrom instead of string parsing for improved efficiency:
<code class="language-go">addr := netip.MustParseAddr("192.168.1.1")
ap := netip.AddrPortFrom(addr, 8080) // More efficient than parsing "192.168.1.1:8080"</code>
  1. Minimize String Conversions: Keep addresses in AddrPort format as much as possible, converting to strings only when necessary.

What's Next?

Our next article will cover the Prefix type, focusing on CIDR notation and subnet operations, completing our exploration of core net/netip types. Until then, leverage the power and efficiency of AddrPort in your network applications!

The above is the detailed content of Working with AddrPort in net/netip: Complete Guide. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn