网站首页 > 文章中心 > 其它

go语言随机提取

作者:小编 更新时间:2023-10-15 10:52:40 浏览量:74人看过

golang 读写二进制文件

我们需要对一些文本进行"明文加密",何为"明文加密"?

从一些错乱的数据中,提取我们想要的数据.

生成错乱的数据(可以随机生成)

这里只是举个简单例子

这样就会该go文件同级目录生成bin文件

并未使用binary.Read()方法

读取到的文本

再根据自己的规则去提取该字符中你想要的数据即可.

golang map的元素遍历为什么是随机的

Map是随机存储的,好像是按内存块的大小放数据.这样存储效率高.但检索效率低.List是会重新划分存储空间,保证连续存储,存的效率低,检索效率高.大概是这个意思,具体的,准确、详细的自己google下.

hashCode() 方法得到其 hashCode 值——每个 Java 对象都有 hashCode() 方法,都可通过该方法获得它的 hashCode 值.得到这个对象的 hashCode 值之后,系统会根据该 hashCode 值来决定该元素的存储位置.

设置了首尾倒置函数,也会出现这种类似情况.还有,你要注意:map中不允许存在重复的键名,你也可以使用其他的方式来实现,比如List,排序的话还得靠你自己来实现了.

golang map源码浅析

golang 中 map的实现结构为: 哈希表 + 链表. 其中链表,作用是当发生hash冲突时,拉链法生成的结点.

好了,全部的只是静态文件 src/runtime/map.go 中的定义. 实际上编译期间会给它加料 ,动态地创建一个新的结构:

上图就是 bmap的内存模型, HOB Hash 指的就是 top hash. 注意到 key 和 value 是各自放在一起的,并不是 key/value/key/value/... 这样的形式.源码里说明这样的好处是在某些情况下可以省略掉 padding 字段,节省内存空间.

map创建方法:

我们实际上是通过调用的 makemap ,来创建map的.实际工作只是初始化了hmap中的各种字段,如:设置B的大小, 设置hash 种子 hash 0.

注意 :

makemap 返回是*hmap 指针, 即 map 是引用对象, 对map的操作会影响到结构体内部 .

使用方式

对应的是下面两种方法

map的key的类型,实现了自己的hash 方式.每种类型实现hash函数方式不一样.

外层遍历bucket 中的链表

建议先不看此部分内容,看完后续 修改 map中元素 - 扩容 操作后 再回头看此部分内容.

扩容前的数据:

等量扩容后的数据:

等量扩容后,查找方式和原本相同, 不多做赘述.

两倍扩容后的数据

两倍扩容后,oldbuckets 的元素,可能被分配成了两部分.查找顺序如下:

使用方式:

步骤如下:

扩容条件 :

扩容的标识 : h.oldbuckets != nil

扩容前:

等量扩容结果

双倍扩容会将old buckets上的元素分配到x, y两个部key 1 B == 0 分配到x部分,key 1 B == 1 分配到y部分

注意: 当前只对双倍扩容描述, 等量扩容只是重新填充了一下元素, 相对位置没有改变.

可以看到,每一遍历生成迭代器的时候,会随机选取一个bucket 以及 一个cell开始. 从前往后遍历,再次遍历到起始位置时,遍历完成.

golang连续生成随机数

const NUM int = 100

for i := 0; i NUM; i += 1 {

}

其实在循环里面这点时间间隔,纳秒也是跟不上的.

还有,你用sleep的方法肯定是不能接受的!!!

GO GOLANG 生成范围随机数

math/rand 中的所有整数函数都生成非负数.

示例 main.go

执行

我自己的需求这样写已足够

【golang详解】go语言GMP(GPM)原理和调度

Goroutine调度是一个很复杂的机制,下面尝试用简单的语言描述一下Goroutine调度机制,想要对其有更深入的了解可以去研读一下源码.

首先介绍一下GMP什么意思:

G ----------- goroutine: 即Go协程,每个go关键字都会创建一个协程.

M ---------- thread内核级线程,所有的G都要放在M上才能运行.

P ----------- processor处理器,调度G到M上,其维护了一个队列,存储了所有需要它来调度的G.

Goroutine 调度器P和 OS 调度器是通过 M 结合起来的,每个 M 都代表了 1 个内核线程,OS 调度器负责把内核线程分配到 CPU 的核上执行

模型图:

避免频繁的创建、销毁线程,而是对线程的复用.

①.)work stealing机制

当本线程无可运行的G时,尝试从其他线程绑定的P偷取G,而不是销毁线程.

如果有空闲的P,则获取一个P,继续执行G0.

如果没有空闲的P,则将G0放入全局队列,等待被其他的P调度.然后M0将进入缓存池睡眠.

如下图

GOMAXPROCS设置P的数量,最多有GOMAXPROCS个线程分布在多个CPU上同时运行

在Go中一个goroutine最多占用CPU 10ms,防止其他goroutine被饿死.

具体可以去看另一篇文章

【Golang详解】go语言调度机制 抢占式调度

当创建一个新的G之后优先加入本地队列,如果本地队列满了,会将本地队列的G移动到全局队列里面,当M执行work stealing从其他P偷不到G时,它可以从全局G队列获取G.

协程经历过程

我们创建一个协程 go func()经历过程如下图:

说明:

G只能运行在M中,一个M必须持有一个P,M与P是1:1的关系.M会从P的本地队列弹出一个可执行状态的G来执行,如果P的本地队列为空,就会想其他的MP组合偷取一个可执行的G来执行;

一个M调度G执行的过程是一个循环机制;会一直从本地队列或全局队列中获取G

上面说到P的个数默认等于CPU核数,每个M必须持有一个P才可以执行G,一般情况下M的个数会略大于P的个数,这多出来的M将会在G产生系统调用时发挥作用.类似线程池,Go也提供一个M的池子,需要时从池子中获取,用完放回池子,不够用时就再创建一个.

work-stealing调度算法:当M执行完了当前P的本地队列队列里的所有G后,P也不会就这么在那躺尸啥都不干,它会先尝试从全局队列队列寻找G来执行,如果全局队列为空,它会随机挑选另外一个P,从它的队列里中拿走一半的G到自己的队列中执行.

如果一切正常,调度器会以上述的那种方式顺畅地运行,但这个世界没这么美好,总有意外发生,以下分析goroutine在两种例外情况下的行为.

Go runtime会在下面的goroutine被阻塞的情况下运行另外一个goroutine:

用户态阻塞/唤醒

系统调用阻塞

当M执行某一个G时候如果发生了阻塞操作,M会阻塞,如果当前有一些G在执行,调度器会把这个线程M从P中摘除,然后再创建一个新的操作系统的线程(如果有空闲的线程可用就复用空闲线程)来服务于这个P.当M系统调用结束时候,这个G会尝试获取一个空闲的P执行,并放入到这个P的本地队列.如果获取不到P,那么这个线程M变成休眠状态, 加入到空闲线程中,然后这个G会被放入全局队列中.

队列轮转

可见每个P维护着一个包含G的队列,不考虑G进入系统调用或IO操作的情况下,P周期性的将G调度到M中执行,执行一小段时间,将上下文保存下来,然后将G放到队列尾部,然后从队列中重新取出一个G进行调度.

M0

M0是启动程序后的编号为0的主线程,这个M对应的实例会在全局变量rutime.m0中,不需要在heap上分配,M0负责执行初始化操作和启动第一个G,在之后M0就和其他的M一样了

G0

G0是每次启动一个M都会第一个创建的goroutine,G0仅用于负责调度G,G0不指向任何可执行的函数,每个M都会有一个自己的G0,在调度或系统调用时会使用G0的栈空间,全局变量的G0是M0的G0

一个G由于调度被中断,此后如何恢复?

中断的时候将寄存器里的栈信息,保存到自己的G对象里面.当再次轮到自己执行时,将自己保存的栈信息复制到寄存器里面,这样就接着上次之后运行了.

我这里只是根据自己的理解进行了简单的介绍,想要详细了解有关GMP的底层原理可以去看Go调度器 G-P-M 模型的设计者的文档或直接看源码

参考: ()

()

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章