Building system utilities, container orchestrators, or network monitoring daemons in Go often requires querying the host machine's hardware and virtual network interfaces. Developers need to programmatically determine hardware MAC addresses, IP subnets, MTU sizes, and interface operational states.
Go's standard library package net provides cross-platform abstractions (net.Interfaces() and net.InterfaceAddrs()) to query low-level network adapter properties across Linux, macOS, and Windows. In this article, we write a complete Go program to inspect and display interface details.
Quick Reference: Enumerating Network Adapters
The standard idiom for iterating active network interfaces and parsing associated IP subnets in Go:
package main
import (
"fmt"
"log"
"net"
)
func main() {
ifaces, err := net.Interfaces()
if err != nil {
log.Fatalf("Failed to retrieve interfaces: %v", err)
}
for _, iface := range ifaces {
fmt.Printf("Name: %s | MAC: %s | MTU: %d | Flags: %v
",
iface.Name, iface.HardwareAddr, iface.MTU, iface.Flags)
}
}1. Complete Go Program to Inspect Interface Details (main.go)
This Go program iterates over every physical and virtual network interface, displaying index IDs, MAC addresses, MTU limits, operational status flags, and assigned IPv4/IPv6 CIDR subnets:
package main
import (
"fmt"
"log"
"net"
)
func main() {
// 1. Fetch slice of all network interfaces on the host system
interfaces, err := net.Interfaces()
if err != nil {
log.Fatalf("Error retrieving network interfaces: %v", err)
}
fmt.Println("=========================================================")
fmt.Println(" HOST NETWORK INTERFACE DISCOVERY DETAILS ")
fmt.Println("=========================================================")
for _, iface := range interfaces {
fmt.Printf("
[ Interface #%d: %s ]
", iface.Index, iface.Name)
// Display MAC Hardware Address
mac := iface.HardwareAddr.String()
if mac == "" {
mac = "None (Virtual / Loopback)"
}
fmt.Printf(" Hardware MAC Address : %s
", mac)
fmt.Printf(" Maximum Transmission : %d bytes (MTU)
", iface.MTU)
fmt.Printf(" Status Flags : %v
", iface.Flags)
// Check boolean interface flags
isUp := (iface.Flags & net.FlagUp) != 0
isLoopback := (iface.Flags & net.FlagLoopback) != 0
fmt.Printf(" Operational State : Up=%t, Loopback=%t
", isUp, isLoopback)
// 2. Fetch unicast and broadcast IP addresses bound to this interface
addrs, err := iface.Addrs()
if err != nil {
fmt.Printf(" Error fetching addresses: %v
", err)
continue
}
fmt.Println(" Bound IP Addresses :")
if len(addrs) == 0 {
fmt.Println(" - No IP address assigned")
}
for _, addr := range addrs {
// Type-assert address to *net.IPNet to extract IP and Subnet Mask
if ipNet, ok := addr.(*net.IPNet); ok {
if ip4 := ipNet.IP.To4(); ip4 != nil {
fmt.Printf(" - IPv4 : %-15s (Mask: %s, CIDR: %s)
",
ip4.String(), ipNet.Mask.String(), ipNet.String())
} else if ip6 := ipNet.IP.To16(); ip6 != nil {
fmt.Printf(" - IPv6 : %s
", ip6.String())
}
}
}
}
}2. Running the Go Utility
Compile and run the Go program from your terminal:
$ go run main.go
=========================================================
HOST NETWORK INTERFACE DISCOVERY DETAILS
=========================================================
[ Interface #1: lo ]
Hardware MAC Address : None (Virtual / Loopback)
Maximum Transmission : 65536 bytes (MTU)
Status Flags : up|loopback
Operational State : Up=true, Loopback=true
Bound IP Addresses :
- IPv4 : 127.0.0.1 (Mask: ffffff00, CIDR: 127.0.0.1/8)
- IPv6 : ::1
[ Interface #2: wlan0 ]
Hardware MAC Address : ac:fd:ce:81:49:b2
Maximum Transmission : 1500 bytes (MTU)
Status Flags : up|broadcast|multicast
Operational State : Up=true, Loopback=false
Bound IP Addresses :
- IPv4 : 192.168.1.105 (Mask: ffffff00, CIDR: 192.168.1.105/24)
- IPv6 : fe80::8802:11fb:12a8:442cUnder the Hood: OS-Specific Kernel Syscalls
Linux (`AF_NETLINK` Sockets): On Linux,
net.Interfaces()opens a Netlink socket (socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) and queriesRTM_GETLINKandRTM_GETADDRkernel messages.macOS / BSD (Routing Sockets): On BSD and macOS systems, Go reads system routing tables via
sysctlwithNET_RT_IFLIST.Windows (`GetAdaptersAddresses`): On Windows, Go invokes the Win32 IP Helper API function
GetAdaptersAddresses().
Comments and corrections