我第一次尝试使用liid包。
在他们的自述文件中说:
请注意,
math
包中的rand.Rand
不安全,不能同时使用。如果您想避免锁定的rand.Source
的潜在争用,则在每个长期运行的go例程中实例化一个,或者使用sync.Pool
,因为它经常在包级函数中观察到。
你能帮我理解这是什么意思吗?如何编写安全代码,以便与诸如ent或gqlgen之类的库并发使用?
?示例:我在我的应用程序中使用以下代码来生成新的id(有时甚至在同一毫秒内生成许多id,这对于ulid
来说很好)。
import (
"math/rand"
"time"
"github.com/oklog/ulid/v2"
)
var defaultEntropySource *ulid.MonotonicEntropy
func init() {
defaultEntropySource = ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0)
}
func NewID() string {
return ulid.MustNew(ulid.Timestamp(time.Now()), defaultEntropySource).String()
}
这是使用包的安全方式吗?
这是使用软件包的安全方式吗?
不,那句话的意思是每个rand。源代码应该是本地的程序,您的defaultEntropySource
rand。源段可能在多个线程之间共享。
创建单个rand。Source每次调用NewID(),为每次调用NewID分配一个新的熵
func NewID() string {
defaultEntropySource := ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0)
return ulid.MustNew(ulid.Timestamp(time.Now()), defaultEntropySource).String()
}
游乐场
和上面一样,但是使用同步。池可以重用以前分配的rand.Source
s
var entropyPool = sync.Pool{
New: func() any {
entropy := ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0)
return entropy
},
}
func NewID() string {
e := entropyPool.Get().(*ulid.MonotonicEntropy)
s := ulid.MustNew(ulid.Timestamp(time.Now()), e).String()
entropyPool.Put(e)
return s
}
游乐场