您的位置:首页 > 健康 > 美食 > 域名停靠app下载_新闻网站界面设计_企业网站seo推广方案_口碑营销有哪些

域名停靠app下载_新闻网站界面设计_企业网站seo推广方案_口碑营销有哪些

2025/4/17 9:37:02 来源:https://blog.csdn.net/lemonth/article/details/146927649  浏览:    关键词:域名停靠app下载_新闻网站界面设计_企业网站seo推广方案_口碑营销有哪些
域名停靠app下载_新闻网站界面设计_企业网站seo推广方案_口碑营销有哪些

6、内存溢出,内存泄漏,内存逃逸

内存溢出:超出给定内存。           

递归没有结束(申请太多对象)

一次性加载超大文件或数据集到内存(如未分页读取)。

大量请求导致内存分配超出系统限制(如未合理设置容器内存上限)。

如无限增长的全局缓存

排查:

  • 容器环境查看 Docker/K8s 内存指标(docker stats 或 kubectl top pods)。

  • 使用 go tool pprof -http=:8080 heap.pprof 分析内存分配热点。

内存泄漏:有些资源没有释放。    文件没有关闭

处理文件,一次性加载过多在内存中

缓存数据无过期策略(如 map 只增不减)。

创建更多的goroutin

排查:

  • 检查全局变量、缓存、第三方库(如 CGO 资源管理)。

  • 使用 defer 确保资源释放(如 defer file.Close())。

  • 检查 Goroutine 数量http://localhost:6060/debug/pprof/goroutine?debug=1 查看 Goroutine 堆栈。

内存逃逸:本来应该分配在栈上时,由于某些原因,它们被分配到了堆上。变量分配到堆上时可能增加 GC 压力,导致内存消耗增大。

func escapeExample() *int {x := 10          // x 是局部变量return &x        // x 的地址被返回,逃逸到堆
}

怎么避免

不要直接返回局部变量的指针。如果需要返回数据,可以直接返回值。

排查

用 pprof 查看堆内存分配

1.2、什么是MVC

1. 用户通过界面(View)进行操作(比如点击按钮或输入 URL)。

2. Controller 接收用户输入,调用 Model 处理业务逻辑或数据库操作。

3. Model 返回结果,Controller 再将结果传递给 View。

4. View 根据数据渲染页面并展示给用户。

5、context

  • Context 的数据结构包含 Deadline,Done,Err,Value,
  • Deadline 方法返回一个 time.Time,表示当前 Context 应该结束的时间,ok 则表示有结束时间,
  • Done 方法当 Context 被某一个操作进行了取消或者超时时候返回的一个 close 的 channel,告诉给 context 相关的函数要停止当前工作然后返回了,
  • Err 表示 context 被取消的原因,
  • Value 方法表示 context 实现共享数据存储的地方,
  • 协程安全的。

9.3、defer关闭资源时,程序中断会被会被关闭吗?

  • defer 在以下情况会执行

    • 正常退出。

    • panic 崩溃(当前函数的 defer)。

    • 捕获中断信号(如 Ctrl+C)。

  • defer 在以下情况不会执行

    • os.Exit 退出。

    • 强制终止(如 kill -9)。

11、Go 多返回值怎么实现的?

  • Go 的多返回值是通过  来实现的

  • 函数的多返回值会被依次压入调用栈中。

 18、闭包

package mainimport "fmt"func main() {f := test()fmt.Println(f(1))//11fmt.Println(f(2))//13
}
func test() func(x int) int {var n int = 10return func(x int)int {n = n + xreturn n}
}

20、切片

20.1、slice

  • copy:相当于覆盖

20.5、切片是否线程安全,为什么不安全,如何保证安全

1. append() 可能导致底层数组扩容,从而导致多个 Goroutine 访问不同的底层数组,产生数据错乱。

2. 多个 Goroutine 可能同时修改 slice 的长度,导致数据竞争(Data Race)。

21.3、为什么不安全,怎么解决安全问题?

Map 线程不安全的原因

  • 底层实现:Go 的 Map 是一个哈希表,包含多个桶(bucket),每个桶存储键值对。并发读写时,多个 Goroutine 可能同时修改桶或触发扩容,导致数据竞争。。

sync.RWMutex读写锁

多个 Goroutine 可以同时读取数据(RLock(),不影响彼此。

写操作需要独占锁(Lock(),确保数据一致性。

21.4、sync.Map

  • 读多写少:适合并发读操作远多于写操作的场景。

  • 通过 无锁读,写 和 延迟删除 等机制减少了锁竞争。

1. 读操作(无锁)
  • 优先从 read 中读取数据,若 read 中不存在且 amended (标记是否有数据在 dirty 中但不在 read 中)为 true,则加锁后从 dirty 中读取。

  • 无锁实现:通过原子操作直接访问 read,避免锁竞争。

2. 写操作(加锁)
  • Store 流程

    1. 先尝试无锁更新 read 中的 entry(通过原子操作)。

    2. 若 read 中不存在该键,则加锁后操作 dirty

      • 若 dirty 未初始化,从 read 中复制未删除的键值对到 dirty(延迟初始化)。

      • 更新 dirty 中的值,并标记 amended 为 true

3. 删除操作(延迟删除)
  • 将 entry 中的指针标记为 nil(逻辑删除),实际数据在 dirty 提升为 read 时才会物理删除。

4. dirty 提升为 read
  • 当 dirty 中的键值对数量超过 read 时,触发 dirty 到 read 的升级(加锁操作)。

  • 升级后,dirty 置为 nilamended 标记为 false

21.8、扩容

  • 等量扩容:并不是扩大容量,buckets数量不变,重新做一遍类似增量扩容的搬迁动作,把松散的键值对重新排列一次。桶内溢出桶数量大于等于2^hash数组长度,长度最大取15,达到长度等量扩容
  • 增量扩容桶内key-v总数/hash数组长度>6.5触发扩容,负载因子(总数/桶数组长度) > 6.5时,桶数组两倍增长。
  • 增量扩容为什么是6.5

        通过开发团队大量测试得出来的,低了占用内存大空间效率会变低,高了插入查找性能变低 

21.10、map底层增删改查

插入

  1. 判断是否初始化,没有panic
  2. 其他线程是否在写入
  3. 产生一个标识标识正在写操作
  4. 根据key值算出哈希值
  5. 取哈希值低位与hmap.B取模确定bucket位置
  6. 判断是否需要进行扩容,分担扩容压力
  7. 查找该key是否已经存在,如果存在则直接更新值
  8. 如果没找到将key,将key插入
  9. 清除之前的正在写标记

查看

  1. 判断map是否初始化,如果没有或数量为0返回0值(为空)
  2. 是否有其他线程并发写入map,是报错
  3. key算处hash值
  4. 对桶取模找到桶位置
  5. 遍历桶链表
  6. 有返v无返回零

22、设计模式

22.1、单例模式

类只会创建一次

1.饿汉模式,线程安全

饿汉模式下的单例写法是最简单的,但它是线程不安全的!

开始就创建,创建好后序继续使用

2.懒汉模式,线程不安全

使用时创建

为什么不安全同时进入类,都是nil所以线程不安全

怎么解决安全问题

2个if。同时进入 强锁,1抢到new。2抢到里面if判断不为nil

加同步锁解决线程安全问题:

24、多线程

24.1、进程、线程、协程有什么区别?

资源

调度方式

通信备注
进程独立的虚拟内存空间,互不干扰进程是操作系统分配资源(CPU、内存、文件等)的最小单位。通过管道、消息队列、共享内存等机制一个进程崩溃不会直接影响其他进程
线程共享进程操作系统内核共享内存

线程间可直接读写同一进程的变量,但需通过锁(如互斥锁)避免竞争。

一个线程崩溃可能导致整个进程崩溃。

程的创建、销毁和调度由操作系统内核管理。

1mb   1000-1500ns 

协程共享线程

程序自行调度

(非操作系统)

共享内存

协程由程序自身控制调度,不依赖操作系统内核。

2kb  切换200ns(纳秒)协程调度器按照调度策略把协程调度到线程中运行

24.5、channel数据结构

总结hchan结构体的主要组成部分有四个:

  • - 用来保存goroutine之间传递数据的循环链表。=====> buf。 qcount(环形数组个数)
  • - 用来记录此循环链表当前发送或接收数据的下标值。=====> sendx和recvx。
  • - 保存向该chan发送和从改chan接收数据的goroutine的队列。==>(写)sendq 和(读) recvq
  • - 保证channel写入和读取数据时线程安全的锁。 =====> lock

发送数据

img

接受数据

img

关闭channel

关闭channel时会把recvq中的G全部唤醒,本该写入G的数据位置为nil。把sendq中的G全部唤醒,但这些G会panic。

24.6、为什么用环形链表

环形链表有头指针和尾指针,可以通过移动指针方便的找到头和尾 

24.7、channel 是否线程安全?锁用在什么地方?

channel 可以在多个 goroutine 之间传递数据,所以必须确保当一个 goroutine 向 channel 发送数据或从 channel 接收数据时, 他 goroutine 不会同时修改 channel 的内部状态。

对循环数组buf进行入队出队操作必须获取互斥锁才能操作数据,锁在这里起到了保护的作用,确保了操作的原子性和一致性。

24.8、nil、关闭的 channel、有数据的 channel,再进行读、写、关闭会怎么样?

nil Channel

  • 读取:阻塞

  • 写入:阻塞

  • 关闭:恐慌(panic)。

关闭的 Channel

  • 读取:完成返回零值和一个 false 值。

  • 写入:恐慌(panic)。

  • 关闭:重复关闭(panic)。

有数据的 Channel

  • 读取:正常读取,不会阻塞。

  • 写入:有其他 goroutine 从该 channel 中读取数据或该 channel 被关闭。

  • 关闭:取完毕后继续读取该 channel 会读取到零值,并且不会阻塞。

24.12、什么是GMP?

组件角色说明数量限制
G (Goroutine)轻量级协程,用户态线程,初始栈仅 2KB,动态扩展(最大 GB 级)理论上无限制(百万级)
M (Machine)操作系统线程(内核线程),负责执行 G 的代码,与 CPU 核心绑定默认最多 10000(可调整)
P (Processor)逻辑处理器,管理 G 的队列和调度策略,连接 G 和 M 的桥梁默认等于 CPU 核心数(GOMAXPROCS

24.13、生命周期

24.14、mutex模式

正常模式

  • 通过自旋获取锁,如果仍未获取锁,通过排队等待,所有等待着按照先入先出顺序排队,当持有锁的goroutine被失败,队伍中第一个等待的锁不会直接拥有锁,需要和后来者竞争,(还在自选阶段的后来者更有优势,因为他们正在cpu运行)。第一个为获取的锁会被插入到队列的头部,(goroutine等待加锁的时间超过1ms后会转为饥饿模式

饥饿模式

  • 饥饿模式下,Mutex 的拥有者将直接把锁交给队列最前面的 waiter。新来的 goroutine 不会尝试获取锁,即使看起来锁没有被持有,它也不会去抢,也不会 spin(自旋),它会乖乖地加入到等待队列的尾部。

返回正常模式

  • 此 waiter 已经是队列中的最后一个 waiter 了,没有其它的等待锁的 goroutine 了;
  • 此 waiter 的等待时间小于 1 毫秒。

25、GC相关

go 1.8混合写屏障机制

GC 开始将栈上的可达对象全部扫描并标记为黑色,栈对象中新建的对象都会被标记成黑色。

栈的垃圾回收

2. 栈的回收策略
  1. 无写屏障:栈上的写操作不触发写屏障。

  2. 最终标记阶段的 STW

    • 在并发标记完成后,执行一次短暂的 STW,扫描所有栈的根对象。

    • 确保栈上的对象引用被正确标记,未被标记的白色对象将被回收。


堆的垃圾回收

1. 并发标记流程
  1. 初始标记(STW)

    • 暂停所有 Goroutine,扫描根对象(栈、全局变量等)。

    • 标记直接可达的对象为灰色。

  2. 并发标记

    • 恢复 Goroutine 执行,后台线程并发标记灰色对象。

    • 混合写屏障监控堆对象的写操作,更新标记状态。

  3. 最终标记(STW)

    • 短暂暂停,扫描残留的栈引用和全局变量。

    • 确保所有存活对象被标记为黑色。

2. 清除阶段(并发)
  • 回收所有白色对象的内存,将其加入空闲链表。

  • 清除阶段无需 STW,与用户程序并发执行。

在次基础上会出现伪命题,栈上想引用一个白色,这个白色不可能是凭空产生的

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com