Golang面试前二夜准备:21-23题

向量数据库大模型云通信

picture.image

Golang面试前二夜准备
题号题目
21Go的Struct能不能比较
22Go的defer原理是什么
23Go的select可以用于什么
  1. Go的Struct能不能比较

  • 相同struct类型的可以比较
  • 不同struct类型的不可以比较,编译都不过,类型不匹配
  
package main  
  
import "fmt"  
  
func main() {  
    type A struct {  
        a int  
    }  
    type B struct {  
        a int  
    }  
    a := A{1}  
    //b := A{1} //a == b 成立  
    b := B{1}  
    if a == b { //不成立 类型不匹配  
        fmt.Println("a == b")  
    }else{  
        fmt.Println("a != b")  
    }  
}   
  
output:  
  
> command-line-arguments [command-line-arguments.test]  
> ./.go:14:7: invalid operation: a == b (mismatched types A and B)   

  1. Go的defer原理是什么

golang defer三规三返

  1. Go的select可以用于什么

golang 的 select 机制是,监听多个channel,每一个 case 是一个事件,可以是读事件也可以是写事件,随机选择一个执行,可以设置default.

它的作用是:当监听的多个事件都阻塞住会执行default的逻辑。

作用分两种情况:

  1. 使用select case ,ok退出

for-select也是使用频率很高的结构,select提供了多路复用的能力,所以for-select可以让函数具有持续多路处理多个channel的能力。但select没有感知channel的关闭,这引出了2个问题:

  1. 继续在关闭的通道上读,会读到通道传输数据类型的零值,如果是指针类型,读到nil,继续处理还会产生nil。
  2. 继续在关闭的通道上写,将会panic。

问题2可以这么解决:

“ 通道只由发送方关闭,接收方不可关闭,即某个写通道只由使用该select的协程关闭,select中就不存在继续在关闭的通道上写数据的问题。

问题1可以使用,ok来检测通道的关闭。

  
go func() {  
 // in for-select using ok to exit goroutine  
 for {  
  select {  
  case x, ok := <-in:  
   if !ok {  
    return  
   }  
   fmt.Printf("Process %d\n", x)  
  case <-t.C:  
   fmt.Printf("Working...")  
  }  
 }  
}()  

  1. 使用退出通道退出
  
func worker(stopCh <-chan struct{}) {  
 go func() {  
  defer fmt.Println("worker exit")  
  // Using stop channel explicit exit  
  for {  
   select {  
   case <-stopCh:  
    fmt.Println("Recv stop signal")  
    return  
   case <-t.C:  
    fmt.Println("Working .")  
   }  
  }  
 }()  
 return  
}  
  

使用,ok来退出使用for-select协程,解决是当读入数据的通道关闭时,没数据读时程序的正常结束。想想下面这2种场景,,ok还能适用吗?

接收的协程要退出了,如果它直接退出,不告知发送协程,发送协程将阻塞。启动了一个工作协程处理数据,如何通知它退出?

使用一个专门的通道,发送退出的信号,可以解决这类问题。以第2个场景为例,协程入参包含一个停止通道stopCh,当stopCh被关闭,case <-stopCh会执行,直接返回即可。

当我启动了100个worker时,只要main()执行关闭stopCh,每一个worker都会都到信号,进而关闭。如果main()向stopCh发送100个数据,这种就低效了。

通过channel控制子goroutine的方法可以总结为:循环监听一个channel,一般来说是for循环里放一个select监听channel以达到通知子goroutine的效果。再借助Waitgroup,主进程可以等待所有协程优雅退出后再结束自己的运行,这就通过channel实现了优雅控制goroutine并发的开始和结束。

因此在退出协程的时候需要注意:

  1. 发送协程主动关闭通道,接收协程不关闭通道。使用技巧:把接收方的通道入参声明为只读,如果接收协程关闭只读协程,编译时就会报错。
  2. 协程处理1个通道,并且是读时,协程优先使用for-range,因为range可以关闭通道的关闭自动退出协程。
  3. ok可以处理多个读通道关闭,需要关闭当前使用for-select的协程。
  4. 显式关闭通道stopCh可以处理主动通知协程退出的场景。
0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
KubeZoo: 轻量级 Kubernetes 多租户方案探索与实践
伴随云原生技术的发展,多个租户共享 Kubernetes 集群资源的业务需求应运而生,社区现有方案各有侧重,但是在海量小租户的场景下仍然存在改进空间。本次分享对现有多租户方案进行了总结和对比,然后提出一种基于协议转换的轻量级 Kubernetes 网关服务:KubeZoo,该方案能够显著降低多租户控制面带来的资源和运维成本,同时提供安全可靠的租户隔离性。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论