IP Tool

The following example program demonstrates how to properly use Go’s pflag library in a CLI application. The program uses an external service to determine the hosts IPv4 or IPv6 address and can be compiled on both Windows and Linux..

Go
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"

	"github.com/spf13/pflag" // pflag package for command-line flag parsing
)

// GetIP fetches the current public IPv4 or IPv6 address using icanhazip.com.
// It returns the IP address as a trimmed string.
func GetIP(ipv6 bool) (string, error) {
	// Default to IPv4 endpoint
	url := "https://ipv4.icanhazip.com"
	if ipv6 {
		// Use IPv6 endpoint if flag is set
		url = "https://ipv6.icanhazip.com"
	}

	resp, err := http.Get(url)
	if err != nil {
		return "", fmt.Errorf("failed to get IP from %s: %v", url, err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("failed to read IP response: %v", err)
	}

	return strings.TrimSpace(string(body)), nil
}

func main() {
	// Define command-line flags.
	// --ipv6 flag (default false, using IPv4 by default)
	ipv6 := pflag.Bool("ipv6", false, "Use IPv6 instead of IPv4")
	// --format flag: accepts "text" (default) or "json"
	format := pflag.String("format", "text", "Output format: text or json")
	pflag.Parse() // Parse flags

	// Fetch the IP based on the flag.
	ip, err := GetIP(*ipv6)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Output the IP in the chosen format.
	switch strings.ToLower(*format) {
	case "json":
		// Create a JSON object containing the IP.
		result := map[string]string{"ip": ip}
		jsonData, err := json.Marshal(result)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error formatting JSON: %v\n", err)
			os.Exit(1)
		}
		fmt.Println(string(jsonData))
	case "text":
		fallthrough
	default:
		// Simply print the IP address.
		fmt.Println(ip)
	}
}
Expand

It can be created and compiled with the following steps.

Bash
vim iptool.go
go mod init iptool
go: creating new go.mod: module iptool
go: to add module requirements and sums:
	go mod tidy
go mod tidy
go: finding module for package github.com/spf13/pflag
go: found github.com/spf13/pflag in github.com/spf13/pflag v1.0.6
go build -o iptool iptool.go

The following shows usage options and related output.

Bash
/ output

// Flags parsed regardless of order
./iptool --ipv6 --format=json
{"ip":"2600:1700:24d1:1490::99"}

./iptool --format=json --ipv6
{"ip":"2600:1700:24d1:1490::99"}

// Defaults used if no flags provided
./iptool
70.148.4.225