In Go, we usually expect reasonable performance and brevity. For example,

    package main
    
    import (
    	"encoding/hex"
    	"fmt"
    	"math/big"
    	"regexp"
    	"strings"
    )
    
    func formatSerial(serial *big.Int) string {
    	b := serial.Bytes()
    	buf := make([]byte, 0, 3*len(b))
    	x := buf[1*len(b) : 3*len(b)]
    	hex.Encode(x, b)
    	for i := 0; i < len(x); i += 2 {
    		buf = append(buf, x[i], x[i+1], ':')
    	}
    	return string(buf[:len(buf)-1])
    }
    
    func main() {
    	fmt.Println(formatSerial(big.NewInt(1234)))
    	// "04:d2"
    	fmt.Println(formatSerial(big.NewInt(123456)))
    	// "01:e2:40"
    	fmt.Println(formatSerial(big.NewInt(1234567891011121314)))
    	// "11:22:10:f4:b2:d2:30:a2"
    }

Output:

    04:d2
    01:e2:40
    11:22:10:f4:b2:d2:30:a2

Benchmark: `serial := big.NewInt(1234567891011121314)`:

    BenchmarkPeterSO    	 3000000	   552 ns/op	    72 B/op	     3 allocs/op
    BenchmarkKissgyorgy 	  500000	  2545 ns/op	   120 B/op	     7 allocs/op
    Benchmark200Success 	   30000	 40675 ns/op	 40675 B/op	    35 allocs/op