golang Golang超时和滴答循环

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang Golang超时和滴答循环相关的知识,希望对你有一定的参考价值。

// keepDoingSomething will keep trying to doSomething() until either
// we get a result from doSomething() or the timeout expires
func keepDoingSomething() (bool, error) {
	timeout := time.After(5 * time.Second)
	tick := time.Tick(500 * time.Millisecond)
	// Keep trying until we're timed out or got a result or got an error
	for {
		select {
		// Got a timeout! fail with a timeout error
		case <-timeout:
			return false, errors.New("timed out")
		// Got a tick, we should check on doSomething()
		case <-tick:
			ok, err := doSomething()
			// Error from doSomething(), we should bail
			if err != nil {
				return false, err
			// doSomething() worked! let's finish up
			} else if ok {
				return true, nil
			}
			// doSomething() didn't work yet, but it didn't fail, so let's try again
			// this will exit up to the for loop
		}
	}
}

Golang✔️走进 Go 语言✔️ 第十七课 select & 超时和非阻塞

【Golang】✔️走进 Go 语言✔️ 第十七课 select & 超时和非阻塞

概述

Golang 是一个跨平台的新生编程语言. 今天小白就带大家一起携手走进 Golang 的世界. (第 17 课)

select

Select 是 Go 中的一个控制结构. 类似于 switch 语句. 如果没有 case 可运行, select 将会阻塞, 直到有 case 可以运行.

select 语法:

  • 每个 case 都必须是一个通信
  • 所有 channel 表达式都会被求值
  • 所有被发送的表达式都会被求值
  • 如果任意某个通信可以进行, 它就执行, 忽略其他
  • 如果有多个 case 都可以运行, select 会随机挑出一个

例子:

 package main

import (
	"fmt"
	"time"
)

func main() {

	// 创建通道
	channel1 := make(chan string)
	channel2 := make(chan string)

	go func() {
		time.Sleep(time.Second)
		channel1 <- "1 号"
	}()

	go func() {
		time.Sleep(time.Second * 2)
		channel2 <- "2 号"
	}()

	// select
	for i := 0; i < 2; i++ {
		select {
		
		case msg1 := <- channel1:
			fmt.Println("received", msg1)
		
		case msg2 := <- channel2:
			fmt.Println("received", msg2)
		}
	}
	
}

输出结果:

received 1 号
received 2 号

超时

超时 (Timeout) 对于连接到外部资源或在不需要绑定执行时间的程序很重要.

例子:

package main

import (
	"fmt"
	"time"
)

func main() {

	// 创建通道
	channel1 := make(chan string)

	// 协程
	go func() {
		time.Sleep(time.Second * 5)
		channel1 <- "1 号"
	}()

	// select
	select {
	
	case msg1 := <-channel1:
		fmt.Println(msg1)
	
	case <-time.After(time.Second * 3):
		fmt.Println("timeout")
	}
	
}

输出结果:

timeout

非阻塞

通道的如果同时发送和接收就会阻塞. 但是, 可以使用 select 和 default 字句来实现非阻塞发送, 接收. 也可以实现非阻塞多路通信.


例子:

package main

import "fmt"

func main() {

	// 创建缓冲通道, 如果不加缓冲, 都会选择defalut
	message := make(chan string, 1)

	// 接收
	select {

	case msg := <- message:
		fmt.Println("收到消息: ", msg)

	default:
		fmt.Println("没有收到消息")
	}

	// 发送
	select {

	case message <- "hello world":
		fmt.Println("send message")

	default:
		fmt.Println("no message")
	}

	// 接收
	select {

	case msg := <- message:
		fmt.Println("收到消息: ", msg)

	default:
		fmt.Println("没有收到消息")
	}

}

输出结果:

没有收到消息
send message
收到消息 hello world

以上是关于golang Golang超时和滴答循环的主要内容,如果未能解决你的问题,请参考以下文章

Golang select 详解

Golang select 详解

golang网络通信超时设置

golang channel 超时如何处理

订单超时自动取消golang

Golang✔️走进 Go 语言✔️ 第十七课 select & 超时和非阻塞