guid.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package guid
  2. import (
  3. "crypto/rand"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "strconv"
  8. "strings"
  9. )
  10. var _ = (json.Marshaler)(&GUID{})
  11. var _ = (json.Unmarshaler)(&GUID{})
  12. type GUID [16]byte
  13. func New() GUID {
  14. g := GUID{}
  15. _, err := io.ReadFull(rand.Reader, g[:])
  16. if err != nil {
  17. panic(err)
  18. }
  19. return g
  20. }
  21. func (g GUID) String() string {
  22. return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:])
  23. }
  24. func FromString(s string) GUID {
  25. if len(s) != 36 {
  26. panic(fmt.Sprintf("invalid GUID length: %d", len(s)))
  27. }
  28. if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
  29. panic("invalid GUID format")
  30. }
  31. indexOrder := [16]int{
  32. 0, 2, 4, 6,
  33. 9, 11,
  34. 14, 16,
  35. 19, 21,
  36. 24, 26, 28, 30, 32, 34,
  37. }
  38. byteOrder := [16]int{
  39. 3, 2, 1, 0,
  40. 5, 4,
  41. 7, 6,
  42. 8, 9,
  43. 10, 11, 12, 13, 14, 15,
  44. }
  45. var g GUID
  46. for i, x := range indexOrder {
  47. b, err := strconv.ParseInt(s[x:x+2], 16, 16)
  48. if err != nil {
  49. panic(err)
  50. }
  51. g[byteOrder[i]] = byte(b)
  52. }
  53. return g
  54. }
  55. func (g GUID) MarshalJSON() ([]byte, error) {
  56. return json.Marshal(g.String())
  57. }
  58. func (g *GUID) UnmarshalJSON(data []byte) error {
  59. *g = FromString(strings.Trim(string(data), "\""))
  60. return nil
  61. }