-1

In order to make semi-random slugs, I'd like to use first 8 characters of uuid. So I have

import (
    fmt
    "github.com/satori/go.uuid"
)

    u1 := uuid.NewV4()
    fmt.Println("u1 :", u1)

    runes := []rune(u1)
    slug := string(runes[0:7]) 

But in compile time I get this error:

cannot convert u1 (type uuid.UUID) to type []rune

How can I fix it?

Karlom
  • 13,323
  • 27
  • 72
  • 116
  • 1
    Why are you trying to convert it to `[]rune`? A UUID can only contain hex characters in it's string representation. Why not just use the `String()` method? – JimB Dec 06 '17 at 14:02
  • @JimB, I'm a go noob and that's a snippet that I found to cut string to certain length. Appreciate a complete answer with code example. – Karlom Dec 06 '17 at 14:04
  • 2
    you should probably start with the basic documentation, maybe run through the [Tour of Go](https://tour.golang.org). Cutting&pasting without knowing why rarely ends well. – JimB Dec 06 '17 at 14:08

2 Answers2

4

There is no need to convert the UUID to a []rune. That UUID type is stored in a binary representation as a [16]byte. There is a UUID.String() method which you can use to convert to a string, then slice it.

 slug := u1.String()[:7]
JimB
  • 104,193
  • 13
  • 262
  • 255
  • Note that this will contain dashes if you ask for more than 8 characters. – Dietrich Epp Dec 06 '17 at 14:13
  • @DietrichEpp: true, but since they were specifically slicing a UUID, which the string format is part of the specification, I assumed that was intended. Otherwise why use a UUID at all. – JimB Dec 06 '17 at 14:14
  • @DietrichEpp, oh I see, they only wanted it for "randomness" – JimB Dec 06 '17 at 14:16
  • @JimB Shouldn't it be `u1.String()[:8]`, as the "hi" part of the slice is exclusive, so the current version only returns an id with length 7? – Till Kuhn Jun 10 '22 at 09:10
  • @TillKuhn: probably -- I just copied the 7 from the original; if you want 8, then you should use 8. – JimB Jun 10 '22 at 12:35
3

In that package (I just looked at the source code) a UUID is an alias for [16]byte, so you cannot concert it to a rune array, not that you want to.

Try this:

s := hex.EncodeToString(u1.Bytes()[:4])

This will give you 8 hex digits. However, this is still a roundabout way of doing things. A v4 UUID is random except for certain bits, so if you are not using the whole UUID it is more straightforward to just generate 4 random bytes. Use the Read() function in math/rand (which must be seeded) or crypto/rand (which is what the UUID library uses).

b := make([]byte, 4)
rand.Read(b) // Doesn’t actually fail
s := hex.EncodeToString(b)
Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • Which do you reckon yields more random results? `hex.EncodeToString(u1.Bytes()[:4])` or `make([]byte, 4)` ? – Karlom Dec 06 '17 at 14:14
  • @Karlom: `make([]byte, 4)` isn't random, you have to put random data into it. – JimB Dec 06 '17 at 14:17
  • 2
    They are both uniformly random. However, with UUIDs you are generating extra random bits so you can throw them away. Why bother with UUIDs just to throw them away? – Dietrich Epp Dec 06 '17 at 14:18
  • If you read the source of the UUID library, it's using the Go PRNG anyway. Using UUID vs. generating 4 random bytes are definitively equally random. – Adrian Dec 06 '17 at 14:40