golang底层

目录

make和new

数组和切片

map

结构体指针、defer

进程、线程、协程、协程池、死锁

Channel管道

CSP模型、GMP模型

内存、垃圾回收

context.Context上下文

go语言的布隆过滤器

go语言的编程模式


make和new

  1. goland的 make 和 new 的一个区别?

    1. make和new本质是都用于进行内存的分配的两个内置函数,
    2. new用于分配内存并返回指向它的指针
    3. make进行内存分配,并初始化它们长度和容量
  2. new可以对什么数据类型操作,make可以对什么类型操作?

    1. new可以对任何类型进行内存分配
    2. make 只能用于内置的引用类型:切片(slice)、映射(map)和通道(chan)

数组和切片

  1. 数组和切片的区别?
    1. 数组是值类型,包含了固定长度的相同类型的数据结果,底层是一块连续的内存空间。数组作为参数传递的时候,是对数组的拷贝,不会影响到外部数组
    2. 切片是引用类型,长度是动态的,底层由指向底层数组的指针、切片的长度和切片的容量三个部分组成,切片为参数传递的时候传递的是切片的引用(即指向底层数组的指针),所以对切片的修改会影响到外部切片。

map

  1. map类型删除key,它的内存会释放吗?
    1. 会释放内存,但不会立即释放
    2. Map的底层是哈希结构,通过哈希函数将键映射到存储桶bucket(以数组的形式)中,存储的位置是由键的哈希值决定存储在哪个桶中的(当键的哈希值重复时,会将键值对存入存储桶的链表中,在Go 1.9版本之前,哈希冲突是通过链表解决的。从Go 1.9版本开始,当链表长度超过一定阈值时,链表可能会被转换成红黑树,以提高查找效率)。删除map中的键对会导致值的内存变得未被引用,垃圾回收器会在下次运行时回收这部分内存。同时,这并不会立即影响底层存储桶数组的容量,因此底层数组(即存储桶数组)的容量也不会立即缩小,只有在map扩容或缩容(创建新的map将剩余的键值对复制过去,来实现缩容)时才会改变。
    3. map是无序的,go语言没有保证map的遍历顺序,所以每次输出的顺序会不同

结构体指针、defer

  1. 调用函数,传参结构体,还是它的指针?
    1. 传递结构体的指针,可以减少内存的使用
    2. 因为传递结构体函数接收到的是结构体副本,传递指针结构体是递了结构体的内存地址。
  2. go语言中的defer是什么,有多个defer情况下,它的执行顺序是什么样的?
    1. defer是一个关键词,用于定义一个或多个延迟执行的函数调用
    2. defer 通常用于释放资源,比如文件关闭、解锁、清理等,确保这些操作在函数执行完之前被调用,避免资源泄露
    3. 当有多个defer语句的时候,执行顺序遵循后进先出的的原则,类似于栈的数据结构,写在函数最后的defer会最先被执行。

进程、线程、协程、协程池、死锁

  1. 进程和线程的区别是什么,线程和协程的区别是什么?
    1. 进程是CPU资源分配和执行的一个基本单位,进程可以包含一个或多个线程,进程间是相互隔离的
    2. 线程是CPU调度器度和执行的一个基本单位,同一进程中的线程共享进程的资源,可以进行并发执行。
    3. 协程的调度通常由运行时的调度器来完成,而不是操作系统的,协程间通信通常通过通道(Channels)来实现,协程比线程更轻量级,开销更小
  2. goland的多个协程怎么怎么保证数据的正确性?
    1. 使用互斥锁sync.Mutex确保多个协程访问共享数据时数据的正确性,同一时间只能有一个协程来进程操作,完成操作后由下一个协程操作
    2. 通道Go 语言的通道可以用来在协程之间安全地传递数据。通过通道传递数据(从一个协程发送数据到另一个协程),可以避免直接共享内存,从而简化同步问题
  3. 协程池是什么,作用是什么?
    1. 协程池是一种管理goroutine生命周期和数量的技术,类似于线程池。它通过限制同时运行的goroutine数量,达到资源合理分配和避免资源耗尽的目的,协程池通常包含任务队列和固定数量的worker goroutines两部分,任务队列用于存放待处理的任务,worker goroutines负责从队列中取出并执行任务
    2. 协程池的优点、是由哪些部分组成的:
      1. 降低并发任务的开销:在并发编程中,创建和销毁goroutine的开销是比较大的。使用协程池可以避免频繁地创建和销毁goroutine,而是重复利用已经创建好的goroutine,从而降低了开销
      2. 控制并发的数量:协程池可以限制并发任务的数量,防止系统资源被过度占用。通过控制协程池中工作协程的数量,可以确保系统在高并发情况下仍能保持稳定和可控的状态,避免资源耗尽或系统崩溃
      3. 提高性能和吞吐量:协程池能够有效地管理并发任务的执行,通过合理调度和分配任务,可以最大限度地利用系统资源,提高并发性能和吞吐量。通过避免创建大量的goroutine和减少上下文切换,可以减少系统负载,提高处理能力
  4. 当协程的创建量过大时会造成什么问题,怎么去解决?
    1. 当协程数量过多时会占用大量内存导致性能下降
    2. 使用sync.Pool临时对象的对象池,减少内存分配和垃圾回收的开销,避免频繁创建和销毁对象
  5. Go语言什么情况下会发生死锁,发生了死锁如何解决?
    1. 死锁
      1. 互斥锁:两个或多个 goroutine 试图同时访问同一个互斥资源,但只有一个可以访问,其他的必须等待。
      2. 循环等待:两个或多个 goroutine(Go 语言中的轻量级线程)互相等待对方的资源释放,导致所有参与的 goroutine 都无法继续执行的情况。
    2. 解决死锁:
      1. 避免循环等待:尽量避免出现多个 goroutine 之间循环等待资源的情况。
      2. 加锁顺序:确保 goroutine 在获取锁的顺序上保持一致,避免因为不同的加锁顺序导致死锁。
      3. 超时机制:在等待资源时加入超时机制,避免无限期地等待资源释放。
    3. 如果已经产生死锁了:
      1. 判断死锁情况,查看导致错误的死锁信息
      2. 如果死锁是由新引入的代码问题导致的,可以执行代码回滚或者热修复,确保新代码不会影响线上稳定性。
      3. 代码修改重新部署之前进行验证,避免再次出现死锁问题

Channel管道

  1. Channel的底层是什么结构
  2. 师德师风

CSP模型、GMP模型

  1. CSP 是一种并发模型,它的核心思想是通过消息传递来进行进程间通信,而不是通过共享内存。Go 通过 goroutine 和 channel 来实现这一理念(GMP)。 在 Go 语言中,goroutine 是一种轻量级的线程,创建和销毁成本很低,非常适合进行大量并发操作。goroutine 之间通过 channel 进行通信,实现数据同步和协作,避免了传统多线程编程中的竞争条件和锁的使用。channel 是 Go 语言中的一种数据管道,可以在不同的 goroutine 之间传递数据。通过 channel,我们可以很方便地实现goroutine 之间的通信和同步

  2. 并发GMP模型:可以在不同的 M 之间移动 goroutine,从而避免某个 M 线程过载或空闲,当系统中有空闲的 P时,可以将其借用给繁忙的 M,从而最大化系统资源利用。

    1. P调度器:负责维护 goroutine 队列,以及将 goroutine 分配给 M 来执行
    2. M线程:代表操作系统级别的线程,它是实现并发的实际执行体
    3. G协程:是 Go 语言中的轻量级线程,代表一个独立的执行单元

内存、垃圾回收

  1. Go语言垃圾回收——三色标记法(v1.5后)+混写屏障机制(V1.8后)
    1. 把新创建的对象,默认的颜色都标记为“白色”
    2. 每次GC回收开始,然后从根节点开始遍历所有对象,把遍历到的对象从白色集合放入“灰色”集合
    3. 遍历灰色集合,将灰色对象引用的对象从白色集合放入到灰色集合,之后将此灰色对象放入到黑色集合
    4. 重复第三步,直到灰色中无任何对象
    5. 回收所有的白色标记的对象,也就是回收垃圾

资源泄露

  1. 哪些问题会导致go语言资源的泄露
    1. 文件未关闭,资源无法释放。使用defer 文件.close关闭连接
    2. 未关闭的数据库连接导致连接池连接数量增加:defer.close()来关闭连接
    3. 未关闭的阻塞的管道。Close(管道名称)关闭不使用的管道
    4. 对于重复创建和销毁的对象:sync.pool避免对象重复并且减少GC的压力

context.Context上下文

  1. go语言中context.Context上下文是什么?有什么作用?
    1. Go语言的 context 包主要用于在多个goroutine之间传递上下文信息,比如:截止时间、取消信号以及携带请求特定值。在并发编程中,它可以帮助我们更好地管理goroutine的生命周期和资源使用。
    2. 具体来说,context 有以下几个主要作用: 1)控制并发任务的生命周期:通过传递 context ,可以方便地通知所有相关的goroutine停止运行,从而避免资源泄露。2)传递请求范围内的数据:在处理context 可以用来传递一些请求相关的数据,比如认证Token、用户信息等。3)设置HTTP请求时,超时时间:可以通过 context 来设置某个操作的超时时间,一旦超时,相关的goroutine就会被取消。

go语言的布隆过滤器

  1. 布隆过滤器(Bloom Filter)的实现原理?
    1. 布隆过滤器是一种用于判断一个元素是否可能在一个集合中的数据结构。它使用位数组(通常是一个很大的二进制数组)和多个哈希函数
    2. 当要添加一个元素到布隆过滤器时,通过多个不同的哈希函数对这个元素进行计算,得到多个哈希值。然后将位数组中这些哈希值对应的位设置为 1 。
      • 哈希种子:是用于初始化哈希函数的随机值

go语言的编程模式

  1. Go语言的编程有哪些?
    1. 并发编程:(通过Goroutine和Channel等机制,可以轻松地实现并发和并行处理)
    2. 面向对象编程:(提供了结构体(struct)和接口(interface),可以模拟面向对象编程的一些特性,如封装和多态,代码更加模块化)设计模式:
      • 工厂模式:工厂模式可以隐藏对象如何被创建的细节,允许在不修改现有代码的基础上扩展新的产品,遵循开闭原则,通过传递不同的参数给工厂,由工厂决定实例化哪个具体类
      • 单例模式:可以通过sync.Once创建
        • 它内部包含一个布尔标志,用于记录初始化是否已经开始或完成。当 sync.0nce 的 Do 方法被调用时,如果初始化尚未开始,它将执行传入的函数,并且阻塞其他goroutines 执行相同的初始化操作。一旦初始化函数执行完成,Do方法会记录初始化已完成,后续的调用将直接返回,不再执行初始化函数。
      • 观察者模式:观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。Go语言可以通过channel实现​
  2. 分布式编程
    1. 分布式编程:(Go语言的并发特性和网络库使其非常适合构建分布式系统和微服务架构,需要考虑服务发现、负载均衡、数据一致性等机制,以及使用RPC(远程过程调用)、RESTful API等通信协议)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值