上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
math 1.18
常用的是 整数 和 浮点数 最大最小值定义。
const ( MaxInt = 1<<(intSize-1) - 1 MinInt = -1 << (intSize - 1) MaxInt8 = 1<<7 - 1 MinInt8 = -1 << 7 ... MaxUint64 = 1<<64 - 1 ) const ( MaxFloat32 = 0x1p127 * (1 + (1 - 0x1p-23)) MaxFloat64 = 0x1p1023 * (1 + (1 - 0x1p-52)) ... )
rand
伪随机性(pseudo random)是指一个过程似乎是随机的,但实际上并不是。
伪随机数(或称伪乱数)使用确定性算法计算出 “随机” 数序。
如种子(seed)不变,那么所返回伪随机数序也不变。优点是计算比较简单。
如注重安全,建议使用 crypto/rand
包。
或从 /dev/random
、 /dev/urandom
读取数据进行处理。(前者会阻塞)
import ( "math/rand" "time" ) func main() { // 固定种子,导致每次输出的随机数列相同。 // var seed int64 = 1 var seed int64 = time.Now().UnixNano() rnd := rand.New(rand.NewSource(seed)) for i := 0; i < 10; i++ { println(rnd.Int()) } }
包函数( Int
、 Intn
...)并发安全。
如果要批量获取,建议新建 Rand
对象,减少锁定。
Perm
:返回数列切片。(乱序)Read
:填充字节切片。(byte
)Shuffle
:洗牌。
package main import ( "math/rand" "fmt" "sort" "time" ) func init() { rand.Seed(time.Now().UnixNano()) } func main() { x := rand.Perm(10) c := make([]int, len(x)) copy(c, x) sort.Ints(c) fmt.Println(x) fmt.Println(c) } // [0 2 8 7 5 9 1 4 3 6] // [0 1 2 3 4 5 6 7 8 9]
func main() { b := make([]byte, 10) rand.Read(b) fmt.Println(b) } // [215 249 246 45 137 234 155 43 181 255] 以实际输出为准。
func main() { d := [...]int{1, 2, 3, 4, 5} rand.Shuffle(len(d), func(i, j int){ d[i], d[j] = d[j], d[i] }) fmt.Println(d) } // [3 5 1 2 4] 随机,以实际输出为准。
源码剖析
随机数由 Source
生成,非并发安全。
// rand.go func New(src Source) *Rand { s64, _ := src.(Source64) return &Rand{src: src, s64: s64} } func (r *Rand) Int() int { u := uint(r.Int63()) return int(u << 1 >> 1) // clear sign bit if int == int32 } func (r *Rand) Int63n(n int64) int64 { max := int64((1 << 63) - 1 - (1<<63)%uint64(n)) v := r.Int63() for v > max { v = r.Int63() } return v % n }
有个 globalRand
为包函数提供服务,是并发安全封装。
同样需先调用 Seed
设置随机种子。
// rand.go var globalRand = New(&lockedSource{src: NewSource(1).(*rngSource)}) func Seed(seed int64) { globalRand.Seed(seed) } func Int() int { return globalRand.Int() }
type lockedSource struct { lk sync.Mutex src *rngSource } func (r *lockedSource) Int63() (n int64) { r.lk.Lock() n = r.src.Int63() r.lk.Unlock() return }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论