Go语言三种方式实现超时退出

1、Go语言三种方式实现超时退出

1.1 context.WithTimeout/context.WithDeadline + time.After

// time.After(time.Duration(time.Millisecond * 700))
package main

import (
	"context"
	"fmt"
	"time"
)

// Golang三种方式实现超时退出-方法1
// 场景:设定一个超时时间,若是在指定超时时间后没有返回结果,则重试
func main() {
	// 经过context的WithTimeout设置一个有效时间为800毫秒的context
	// 该context会在耗尽800毫秒后或者方法执行完成后结束,结束的时候会向通道ctx.Done发送信号
	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
	// 注意,这里要记得调用cancel(),否则即便提早执行完了,还要傻傻等到800毫秒后context才会被释放
	defer cancel()
	go func(ctx context.Context) {
		// 发送HTTP请求
		fmt.Println("处理请求!")
		time.Sleep(800 * time.Millisecond)
		fmt.Println("请求处理完毕!")
	}(ctx)
	select {
	case <-ctx.Done():
		fmt.Println("call successfully!!!")
		return
	// 这里已经设置了context的有效时间,为何还要加上这个time.After呢
	// 这是由于该方法内的context是本身声明的,能够手动设置对应的超时时间,可是在大多数场景,这里的ctx是从上游一直传递过来的,
	// 对于上游传递过来的context还剩多少时间,咱们是不知道的,因此这时候经过time.After设置一个本身预期的超时时间就颇有必要了
	case <-time.After(time.Duration(time.Millisecond * 700)):
		fmt.Println("timeout!!!")
		return
	}
}
# 程序输出
处理请求!
timeout!!!

修改超时时间:

// time.After(time.Duration(time.Millisecond * 1000))
package main

import (
	"context"
	"fmt"
	"time"
)

// Golang三种方式实现超时退出-方法1
// 场景:设定一个超时时间,若是在指定超时时间后没有返回结果,则重试
func main() {
	// 经过context的WithTimeout设置一个有效时间为800毫秒的context
	// 该context会在耗尽800毫秒后或者方法执行完成后结束,结束的时候会向通道ctx.Done发送信号
	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
	// 注意,这里要记得调用cancel(),否则即便提早执行完了,还要傻傻等到800毫秒后context才会被释放
	defer cancel()
	go func(ctx context.Context) {
		// 发送HTTP请求
		fmt.Println("处理请求!")
		time.Sleep(800 * time.Millisecond)
		fmt.Println("请求处理完毕!")
	}(ctx)
	select {
	case <-ctx.Done():
		fmt.Println("call successfully!!!")
		return
	// 这里已经设置了context的有效时间,为何还要加上这个time.After呢
	// 这是由于该方法内的context是本身申明的,能够手动设置对应的超时时间,可是在大多数场景,这里的ctx是从上游一直传递过来的,
	// 对于上游传递过来的context还剩多少时间,咱们是不知道的,因此这时候经过time.After设置一个本身预期的超时时间就颇有必要了
	case <-time.After(time.Duration(time.Millisecond * 1000)):
		fmt.Println("timeout!!!")
		return
	}
}
# 程序输出
处理请求!
请求处理完毕!
call successfully!!!

1.2 context.WithTimeout/context.WithDeadline + time.NewTimer

// time.NewTimer(time.Duration(time.Millisecond * 700))
package main

import (
	"context"
	"fmt"
	"time"
)

// Golang三种方式实现超时退出-方法2
// 使用time.NewTimer
func main() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
	defer cancel()
	timer := time.NewTimer(time.Duration(time.Millisecond * 700))
	go func(ctx context.Context) {
		// 发送HTTP请求
		fmt.Println("处理请求!")
		time.Sleep(800 * time.Millisecond)
		fmt.Println("请求处理完毕!")
	}(ctx)
	select {
	case <-ctx.Done():
		timer.Stop()
		timer.Reset(time.Second)
		fmt.Println("call successfully!!!")
		return
	case <-timer.C:
		fmt.Println("timeout!!!")
		return
	}
}
# 程序输出
处理请求!
timeout!!!

修改超时间:

// time.NewTimer(time.Duration(time.Millisecond * 1000))
package main

import (
	"context"
	"fmt"
	"time"
)

// Golang三种方式实现超时退出-方法2
// 使用time.NewTimer
func main() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
	defer cancel()
	timer := time.NewTimer(time.Duration(time.Millisecond * 1000))
	go func(ctx context.Context) {
		// 发送HTTP请求
		fmt.Println("处理请求!")
		time.Sleep(800 * time.Millisecond)
		fmt.Println("请求处理完毕!")
	}(ctx)
	select {
	case <-ctx.Done():
		timer.Stop()
		timer.Reset(time.Second)
		fmt.Println("call successfully!!!")
		return
	case <-timer.C:
		fmt.Println("timeout!!!")
		return
	}
}
# 程序输出
处理请求!
请求处理完毕!
call successfully!!!

1.3 channel + time.After/time.NewTimer

// time.After(time.Duration(700 * time.Millisecond))
package main

import (
	"context"
	"fmt"
	"time"
)

// Golang三种方式实现超时退出-方法3
// 使用通道
func main() {
	ctx := context.Background()
	done := make(chan struct{}, 1)
	go func(ctx context.Context) {
		// 发送HTTP请求
		fmt.Println("处理请求!")
		time.Sleep(800 * time.Millisecond)
		fmt.Println("请求处理完毕!")
		done <- struct{}{}
	}(ctx)
	select {
	case <-done:
		fmt.Println("call successfully!!!")
		return
	case <-time.After(time.Duration(700 * time.Millisecond)):
		fmt.Println("timeout!!!")
		return
	}
}
# 程序输出
处理请求!
timeout!!!

修改超时时间:

// time.After(time.Duration(1000 * time.Millisecond))
package main

import (
	"context"
	"fmt"
	"time"
)

// Golang三种方式实现超时退出-方法3
// 使用通道
func main() {
	ctx := context.Background()
	done := make(chan struct{}, 1)
	go func(ctx context.Context) {
		// 发送HTTP请求
		fmt.Println("处理请求!")
		time.Sleep(800 * time.Millisecond)
		fmt.Println("请求处理完毕!")
		done <- struct{}{}
	}(ctx)
	select {
	case <-done:
		fmt.Println("call successfully!!!")
		return
	case <-time.After(time.Duration(1000 * time.Millisecond)):
		fmt.Println("timeout!!!")
		return
	}
}
# 程序输出
处理请求!
请求处理完毕!
call successfully!!!

你可能感兴趣的:(golang,golang)