我试图在Go中生成一个随机字符串,这是我迄今为止写的代码:

package main

import (
    "bytes"
    "fmt"
    "math/rand"
    "time"
)

func main() {
    fmt.Println(randomString(10))
}

func randomString(l int) string {
    var result bytes.Buffer
    var temp string
    for i := 0; i < l; {
        if string(randInt(65, 90)) != temp {
            temp = string(randInt(65, 90))
            result.WriteString(temp)
            i++
        }
    }
    return result.String()
}

func randInt(min int, max int) int {
    rand.Seed(time.Now().UTC().UnixNano())
    return min + rand.Intn(max-min)
}

我的实现非常缓慢。使用时间的播种在特定的时间内带来相同的随机数,因此循环一次又一次地迭代。我如何改进我的代码?


当前回答

由于golang api的变化,请省略.UTC():

.UnixNano .UTC time.Now()()()——> time.Now () .UnixNano ()

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())
    fmt.Println(randomInt(100, 1000))
}

func randInt(min int, max int) int {
    return min + rand.Intn(max-min)
}

其他回答

每次你设置相同的种子,你会得到相同的序列。当然,如果你在一个快速循环中设置时间的种子,你可能会用同一个种子多次调用它。

在你的例子中,当你调用randInt函数直到你有一个不同的值,你在等待时间(由Nano返回)改变。

对于所有伪随机库,您只需设置一次种子,例如在初始化程序时,除非您特别需要重新生成给定的序列(这通常只用于调试和单元测试)。

在此之后,您只需调用Intn来获得下一个随机整数。

将rand.Seed(time.Now(). utc (). unixnano())行从randInt函数移动到main函数的开头,一切都会更快。失去.UTC()调用,因为:

UnixNano返回t作为Unix时间,即自UTC 1970年1月1日以来经过的纳秒数。

还要注意,我认为你可以简化你的字符串构建:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())
    fmt.Println(randomString(10))
}

func randomString(l int) string {
    bytes := make([]byte, l)
    for i := 0; i < l; i++ {
        bytes[i] = byte(randInt(65, 90))
    }
    return string(bytes)
}

func randInt(min int, max int) int {
    return min + rand.Intn(max-min)
}

@[Denys Séguret]已张贴正确。但在我的情况下,我需要新的种子,因此每次低于代码;

以防你需要快速函数。我这样用。


func RandInt(min, max int) int {
    r := rand.New(rand.NewSource(time.Now().UnixNano()))
    return r.Intn(max-min) + min
}

func RandFloat(min, max float64) float64 {
    r := rand.New(rand.NewSource(time.Now().UnixNano()))
    return min + r.Float64()*(max-min)
}

每次在for循环中调用randint()方法时,都会设置一个不同的种子,并根据时间生成一个序列。但是由于循环在您的计算机中运行得很快,在很短的时间内,种子几乎是相同的,并且由于时间的原因,生成的序列与过去的序列非常相似。因此,将种子设置在randint()方法之外就足够了。

package main

import (
    "bytes"
    "fmt"
    "math/rand"
    "time"
)

var r = rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
func main() {
    fmt.Println(randomString(10))
}

func randomString(l int) string {

    var result bytes.Buffer
    var temp string
    for i := 0; i < l; {
        if string(randInt(65, 90)) != temp {
            temp = string(randInt(65, 90))
            result.WriteString(temp)
            i++
        }
    }
    return result.String()
}

func randInt(min int, max int) int {
    return min + r.Intn(max-min)
}

如果你的目标只是生成一个随机数刺,那么我认为没有必要用多次函数调用或每次重置种子来复杂化它。

最重要的一步是在实际运行rand.Init(x)之前只调用一次种子函数。Seed使用提供的种子值将默认Source初始化为确定状态。因此,建议在实际函数调用伪随机数生成器之前调用它一次。

下面是创建随机数字符串的示例代码

package main 
import (
    "fmt"
    "math/rand"
    "time"
)



func main(){
    rand.Seed(time.Now().UnixNano())

    var s string
    for i:=0;i<10;i++{
    s+=fmt.Sprintf("%d ",rand.Intn(7))
    }
    fmt.Printf(s)
}

我使用Sprintf的原因是它允许简单的字符串格式化。

此外,In rand.Intn(7) Intn作为int返回[0,7)中的非负伪随机数。

为什么这么复杂!

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed( time.Now().UnixNano())
    var bytes int

    for i:= 0 ; i < 10 ; i++{ 
        bytes = rand.Intn(6)+1
        fmt.Println(bytes)
        }
    //fmt.Println(time.Now().UnixNano())
}

这是基于毁灭者的代码但符合我的需要。

它是die 6 (rands int 1 =< i =< 6)

func randomInt (min int , max int  ) int {
    var bytes int
    bytes = min + rand.Intn(max)
    return int(bytes)
}

上面的函数是完全一样的。

我希望这个信息对你有用。