package uuid import ( "crypto/rand" "encoding/hex" "errors" "fmt" "io" "os" "strings" ) const ( ByteCount = 16 dashCount = 4 encodedLength = (ByteCount * 2) + dashCount ) var ( dashIndexes = []int{ 8, 13, 18, 23 } randomReader = rand.Reader ErrBadLength = errors.New( "uuid: str isn't of the correct length", ) ErrBadDashCount = errors.New("uuid: Bad count of dashes in string") ErrBadDashPosition = errors.New("uuid: Bad char in string") ) type UUID [ByteCount]byte func NewFrom(r io.Reader) (UUID, error) { var uuid UUID _, err := io.ReadFull(r, uuid[:]) if err != nil { return UUID{}, err } uuid[6] = (uuid[6] & 0x0f) | 0x40 // v4 uuid[8] = (uuid[8] & 0x3f) | 0x80 // variant 10 return uuid, nil } func New() UUID { uuid, err := NewFrom(randomReader) if err != nil { panic(err) } return uuid } func (uuid UUID) String() string { dst := [encodedLength]byte { 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, 0, '-', 0, 0, 0, 0, '-', 0, 0, 0, 0, '-', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } hex.Encode(dst[ 0:8], uuid[0:4]) hex.Encode(dst[ 9:13], uuid[4:6]) hex.Encode(dst[14:18], uuid[6:8]) hex.Encode(dst[19:23], uuid[8:10]) hex.Encode(dst[24:36], uuid[10:]) return string(dst[:]) } func FromString(str string) (UUID, error) { if len(str) != encodedLength { return UUID{}, ErrBadLength } if strings.Count(str, "-") != dashCount { return UUID{}, ErrBadDashCount } for _, idx := range dashIndexes { if str[idx] != '-' { return UUID{}, ErrBadDashPosition } } hexstr := strings.Join(strings.Split(str, "-"), "") data, err := hex.DecodeString(hexstr) if err != nil { return UUID{}, err } return [ByteCount]byte(data), nil } func Main() { if len(os.Args) < 2 { fmt.Println(New().String()) } else { _, err := FromString(strings.TrimSpace(os.Args[1])) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(3) } } }