Golang面试题目-程序设计题目(四)

题目:假设有一超长切片,元素类型为int,切片中的元素为乱序排列,现需查找切片中是否存在某个元素。

要求:

  1. 5秒内不管有没有查询到该值,都需停止正在运行的程序。

  2. 使用多个goroutine来查找切片中是否存在该元素。

  3. 找到该元素或超时后需立刻停止所有goroutine的执行。

举例:设切片为[1,3,4,2,6,7,23,122...34,545,2321,4546,66],查找目标为123,如果切片中存在目标值,则程序输出【found it】,并立刻停止所有正在执行查找任务的goroutine,反之超时或是没找到该目标值,则输出【not found】,同理停止所有正在执行查找任务的goroutine。

解析:上述题目反复提到一个要求就是第三点【找到该元素或超时后需立刻停止所有goroutine的执行】,需使用channel、计时器、context来实现这个功能。

先使用context.WithChannel创建一个上下文对象传递给每个执行任务的goroutine,外部在找到目标值或程序超时的时候通过调用上下文的取消函数来通知所有执行任务的goroutine来停止工作。

执行任务的goroutine如果找到目标值后,需要通知外部等待执行的主goroutine,这个工作是典型的channel应用场景,可创建一个接收查找结果值的channel,之后就是把它和上下文对象一起传递给正在执行任务的goroutine。

可在执行查找任务的goroutine里接受上下文的取消信号,为不阻塞查找任务,可使用select语句加上default的组合。

拓展下,Go中尽量不要使用共享内存的方式通信,尽量使用通信的方式共享内存。

实现代码如下:

package mainimport (  "context"  "fmt"  "os"  "time")func main() {  timer := time.NewTimer(time.Second * 5)  data := []int{1, 2, 3, 10, 999, 8, 345, 7, 98, 33, 66, 77, 88, 68, 96}  dataLen := len(data)  size := 3  target := 345  ctx, cancel := context.WithCancel(context.Background())  resultChan := make(chan bool)  for i := 0; i < dataLen; i += size {    end := i + size    if end >= dataLen {      end = dataLen - 1    }    go SearchTarget(ctx, data[i:end], target, resultChan)  }  select {  case <-timer.C:    fmt.Fprintln(os.Stderr, "Timeout! Not Found")    cancel()  case <-resultChan:    fmt.Fprintf(os.Stdout, "Found it!\n")    cancel()  }  time.Sleep(time.Second * 2)}func SearchTarget(ctx context.Context, data []int, target int, resultChan chan bool) {  for _, v := range data {    select {    case <-ctx.Done():      fmt.Fprintf(os.Stdout, "Task cancelded! \n")      return    default:    }    // 模拟一个耗时查找,这里只是比对值,真实开发中可以是其他操作    fmt.Fprintf(os.Stdout, "v: %d \n", v)    time.Sleep(time.Millisecond * 1500)    if target == v {      resultChan <- true      return    }  }}

输出结果如下:

上述代码中,goroutine里如果找到目标值,则会发送一个true给resultChan,让外面等待的主goroutine收到一个已找到目标值的信号,这样一来,通过上下文的Done通道和resultChan通道,各个goroutine之间就可以互相通信了。

扫码关注公众号,获取更多优质内容。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值