package main import ( crand "crypto/rand" "encoding/base64" "fmt" mrand "math/rand" "strings" ) const ( // As we only want to get printable ASCII characters, we limit the range of pseudo-random numbers // that can be generated. The total number of printable characters in the ASCII table is 94. This means // that the range of the pseudo-random numbers that the program can generate should be from 0 // to 94, without including 94. Therefore, the values of the MIN and MAX global variables, // are 0 and 94, respectively. MIN = 0 MAX = 94 ) func main() { fmt.Println(randString(20)) randBytes := generateBytes(20) fmt.Println(string(randBytes)) fmt.Println(base64.URLEncoding.EncodeToString(randBytes)) } func randInt(min, max int) int { // Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n) from the default [Source]. It panics if n <= 0. return mrand.Intn(max - min) + min } func randString(len int64) string { // The startChar variable holds the first ASCII character that can be generated by the utility, which, // in this case, is the exclamation mark, which has a decimal ASCII value of 33. startChar := "!" sb := strings.Builder{} var i int64 = 1 for { myRand := randInt(MIN, MAX) newChar := string(startChar[0] + byte(myRand)) sb.WriteString(newChar) if i == len { break } i++ } return sb.String() } func generateBytes(n int64) []byte { b := make([]byte, n) // The rand.Read() function randomly generates numbers that occupy the entire b byte slice. You // need to decode that byte slice using base64.URLEncoding.EncodeToString(b) in order to get // a valid string without any control or unprintable characters. crand.Read(b) // The Read function always returns len(b) and a nil error, so no need to handle the error. return b }