-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: math/rand or crypto/rand: add random strings generators #53447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I even thought of another nice addition while writing this proposal, but it might be extra complicated for nothing (that's why I'm sparing the main message). The idea is to not be limited by single runes, but allow to basically pick up words (it can be used for name generators, or user-friendly urls ?). package main
import (
"math/rand"
)
func main() {
id := rand.StringDictionary(dic, 3) // fish-joystick-robot
} I believe using dictionaries may only prove interesting if you have a very large collection, so just using a Go variable may be harmless in this case. Maybe make dictionary an interface that returns a numerically indexed element ? type Dictionary interface{
Size() int64
Pick(pos int64) string
} So that knowing the total size of the dictionary, the rand method could pick a random position and ask for the element located here. Dictionary could wrap anything like a database where the whole elements would be stored. I also don't think this particular addition needs a |
Nit picking but your UUID implementation is not up to RFC4122.
Example in the |
Yes I gave it as a (probably bad) example of what using custom alphabets could look like. I think the |
StringAlphabet looks questionable, what happens if I put a multi codepoint character in there, like an emoji requiring joiners? as for simple strings, as pointed out above, uuids actually have required set bits, while in other cases it's simple enough to pass the output of rand.Read through a hex/base32/base64 encoding to get a "safe" string |
@seankhliao Maybe package main
import (
"math/rand"
)
var alphabet = []rune("1234567890")
func main() {
id := rand.StringAlphabet(alphabet, 10) // 2834753819
} |
I did not knew about this solution, although it seems less flexible and straightforward than having a string method where you explicitly control the size of the output. |
There is plenty if solutions already:
|
Perhaps to be really flexible: // Choice randomly picks items from input with replacement and copies them to output.
func Choice[T any](input, output []T) {
...
} Then you can pass a I called it |
math/rand
or crypto/rand
: Add random strings generatorsmath/rand
or crypto/rand
: add random strings generators
math/rand
or crypto/rand
: add random strings generators
It seems like this could be done in a separate package outside the standard library. Being able to say exactly what kind of random string you want is a lot of API, since different use cases will want different kinds of strings. |
This proposal has been added to the active column of the proposals project |
A data point: a middle-sized system (200k LOC Go) that talks to dozens of other system. There is a function in a shared private library similar to the one proposed here. It is used 3 times, and around 20 other variants of getting a random string are spread around the codebase, as the requirements for these strings are peculiar, and can't be easily expressed declaratively. We're going to remove library function. |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
@kushuh, if you still need this functionality, try out my random package: It is made to have deterministic randoms during tests, but the package itself doesn't depend on the package main
import (
"math/rand"
"time"
"github.com/adamluzsi/testcase/random"
)
func main() {
rnd := random.New(rand.NewSource(time.Now().Unix())) // or random.New(random.CryptoSeed{})
_ = rnd.StringNC(42, random.CharsetAlpha())
} |
The issue
There are use-cases where we need or could want to generate a random string:
For now neither
math/rand
norcrypto/rand
provide a straightforward solution.Proposal
Add a
String
function to any/both of the rand packages, with only a length parameter to generate a random string of any length.The method would only take a size parameter, that would determine the length of the final string (and possibly panic if this size is negative or too big?).
I think it should also generate a url-safe string, or even only alphanumerics/latin alphabet characters.
StringAlphabet
For a greater coverage, we could also include a more sophisticated method, that would accept an "alphabet" (a user generated set of elements to pick up as runes). Maybe the method could be named
StringAlphabet
? (I'm not the best at naming xD)Where the alphabet argument would be a string of allowed runes to pick up. Could be used for example to generate uuids, where alphabet would look like
"0123456789abcdef"
.Conclusion
I use some working examples I wrote in my packages, so the concept seems to work. However I don't know anything about pseudo-random generators and my solution may be far from optimized.
For the
String
method at least, I found this stackoverflow post that provides a very pleasant solution.The text was updated successfully, but these errors were encountered: