Generate MAC addresses using Go

Below is a simple Go example that generates MAC addresses with support for a custom prefix, control over the locally administered bit, and a configurable number of generated addresses.

The first byte is automatically normalized to ensure correct unicast behavior and optional local administration.

Go Code
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

// normalizeFirstByte ensures the first byte has correct unicast and U/L bits
func normalizeFirstByte(b byte, locallyAdministered bool) byte {
	// Clear I/G bit (bit 0) → unicast
	b &= 0b11111110

	// Set or clear U/L bit (bit 1)
	if locallyAdministered {
		b |= 0b00000010
	} else {
		b &= 0b11111101
	}

	return b
}

// generateMACAddresses generates MAC addresses with the given parameters
func generateMACAddresses(prefix string, locallyAdministered bool, count int) ([]string, error) {
	// Initialize random seed
	rand.Seed(time.Now().UnixNano())

	// Normalize prefix - remove non-hex characters and convert to uppercase
	hexPrefix := ""
	for _, c := range strings.ToUpper(prefix) {
		if (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') {
			hexPrefix += string(c)
		}
	}

	// Validate prefix length (max 5 bytes = 10 hex characters)
	if len(hexPrefix)%2 != 0 || len(hexPrefix) > 10 {
		return nil, fmt.Errorf("prefix must contain 0-5 bytes (0-10 hex characters)")
	}

	// Parse prefix bytes
	var prefixBytes []byte
	for i := 0; i < len(hexPrefix); i += 2 {
		b, err := strconv.ParseUint(hexPrefix[i:i+2], 16, 8)
		if err != nil {
			return nil, fmt.Errorf("invalid hex in prefix: %v", err)
		}
		prefixBytes = append(prefixBytes, byte(b))
	}

	var macs []string

	for i := 0; i < count; i++ {
		// Start with prefix bytes
		bytes := make([]byte, len(prefixBytes))
		copy(bytes, prefixBytes)

		// Generate remaining random bytes
		for len(bytes) < 6 {
			bytes = append(bytes, byte(rand.Intn(256)))
		}

		// Normalize first byte
		bytes[0] = normalizeFirstByte(bytes[0], locallyAdministered)

		// Format as MAC address
		var parts []string
		for _, b := range bytes {
			parts = append(parts, fmt.Sprintf("%02X", b))
		}
		mac := strings.Join(parts, ":")
		macs = append(macs, mac)
	}

	return macs, nil
}

func main() {
	// Example usage
	macs, err := generateMACAddresses(
		"02:AB",           // prefix
		true,              // locally administered
		3,                 // count
	)

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	for _, mac := range macs {
		fmt.Println(mac)
	}
}
Scan to share this page
Copyright © 2020-2026 U00 Open Source Software. All rights reserved.