加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang context

发布时间:2020-12-16 09:29:37 所属栏目:大数据 来源:网络整理
导读:ex1 package mainimport ( "fmt")// 最佳context 实践// Context 目标是实现各个goroutine能及时终止退出。func main() { // Basic ipfsnode setup a := 10 fmt.Println("hhha") fmt.Println(a) } ex2 package mainimport "fmt"// 打印输出, 发送数据到通道

ex1

package main

import (    
    "fmt"
)

// 最佳context 实践
//  Context 目标是实现各个goroutine能及时终止退出。


func main() {
    // Basic ipfsnode setup 
    a := 10
    fmt.Println("hhha")
    fmt.Println(a)  
}

ex2

package main

import "fmt"

// 打印输出, 发送数据到通道
func printHello(ch chan int) {
    fmt.Println("Hello from printHello")
    // 发送一个数据到通道
    ch <- 2
}

func main() {
    /*
    使用make函数,创建一个通道。
    通道是可以带缓冲的, 如果你指定了长度。如ch := make(chan int,2)

    channel可分为三种类型:
        只读channel:只能读channel里面数据,不可写入
        只写channel:只能写数据,不可读
        一般channel:可读可写
    */
    ch := make(chan int)
    //内联goroutine. 定义一个函数,直接go调用.
    //结束时,往通道发一个数据作为信号
    go func(){
        fmt.Println("Hello inline")
        //send a value on channel
        ch <- 1
    }()
    //调用一个函数作为 goroutine
    go printHello(ch)
    fmt.Println("Hello from main")

    //首先从通道中取出一个数据, 并赋值给变量,并打印出来
    i := <- ch
    fmt.Println("Recieved ",i)
    //从通道获取第二个数据
    // 如果不需要它, 可以不赋值给变量
    <- ch
}

ex3

/*
context(上下文): 可以理解为timeout(超时),deadline(终止时间线), 或者一个channel(通道)来指示goroutine停止工作并退出
比如,在系统中, 当调用其它网站的接口时,通常速度比较慢, 但是你又依赖它的及时返回, 所以并不打算把这个进行备份请求。 通常会设置一个超时。
*/


/* 结构如下
// deadline终止时间线,cancelation 取消信号,and request-scoped 请求范围值
// 多个goroutines同时使用,是安全的
type Context interface {
    // Done 方法在Context被取消或超时时返回一个close的channel,close的channel可以作为广播通知,告诉给context相关的函数要停止当前工作然后返回。
    // 当一个父operation启动一个goroutine用于子operation,这些子operation不能够取消父operation。下面描述的WithCancel函数提供一种方式可以取消新创建的Context.
    // Context可以安全的被多个goroutine使用。开发者可以把一个Context传递给任意多个goroutine然后cancel这个context的时候就能够通知到所有的goroutine。
    Done() <-chan struct{}

    // Err方法返回context为什么被取消。
    Err() error

    // Deadline返回context何时会超时。
    Deadline() (deadline time.Time,ok bool)

    // Value返回context相关的数据。
    Value(key interface{}) interface{}
}
*/
// 创建context上下文


// 1. context.Backgrond() ctx Context
// BackGound是所有Context的root,不能够被cancel。
// 这个函数返回一个空的上下文, 这个仅在高层使用(如在main 或者 顶级请求)


/* 2. WithCancel返回一个继承的Context,这个Context在父Context的Done被关闭时关闭自己的Done通道,或者在自己被Cancel的时候关闭自己的Done。
      WithCancel同时还返回一个取消函数cancel,这个cancel用于取消当前的Context。
*/

package main

import (
    "context"
    "log"
    "os"
    "time"
)

var logg *log.Logger

func someHandler() {
    ctx,cancel := context.WithCancel(context.Background())
    go doStuff(ctx)

    //10秒后取消doStuff
    time.Sleep(10 * time.Second)
    cancel()

}

//每1秒work一下,同时会判断ctx是否被取消了,如果是就退出
func doStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)
        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}

func main() {
    logg = log.New(os.Stdout,"",log.Ltime)
    someHandler()
    logg.Printf("down")
}

ex4

/*
context(上下文):
withDeadline withTimeout
*/


/* 结构如下
// deadline终止时间线,ok bool)

    // Value返回context相关的数据。
    Value(key interface{}) interface{}
}
*/
package main

import (
    "context"
    "log"
    "os"
    "time"
)

var logg *log.Logger

//每1秒work一下,同时会判断ctx是否被取消了,如果是就退出
func doStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)
        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}
func timeoutHandler() {
    // 这里在上下文中加入了超时限制, 超时和取消,取其短。
    ctx,cancel := context.WithDeadline(context.Background(),time.Now().Add(2 * time.Second))
    go doStuff(ctx)
    time.Sleep(10 * time.Second)
    cancel()
}

func main() {
    logg = log.New(os.Stdout,log.Ltime)
    timeoutHandler()
    logg.Printf("end")
}

ex5

/*
context(上下文):
withDeadline withTimeout
*/


/* 结构如下
// deadline终止时间线,ok bool)

    // Value返回context相关的数据。
    Value(key interface{}) interface{}
}
*/
package main

import (
    "context"
    "log"
    "os"
    "time"
)

var logg *log.Logger

//每1秒work一下,同时会判断ctx是否被取消了,如果是就退出
func doStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)
        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}
func doTimeOutStuff(ctx context.Context) {
    for {
        time.Sleep(1 * time.Second)

        if deadline,ok := ctx.Deadline(); ok { //设置了deadl
            logg.Printf("deadline set")
            if time.Now().After(deadline) {
                logg.Printf(ctx.Err().Error())
                return
            }

        }

        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        default:
            logg.Printf("work")
        }
    }
}

func timeoutHandler() {
    ctx,cancel := context.WithTimeout(context.Background(),5*time.Second)
    // ctx,time.Now().Add(5*time.Second))
    go doTimeOutStuff(ctx)
    // go doStuff(ctx)

    time.Sleep(10 * time.Second)

    cancel()

}

func main() {
    logg = log.New(os.Stdout,log.Ltime)
    timeoutHandler()
    logg.Printf("end")
}

ex6

/*
context(上下文):
withValue 附加一些(不可变)数据, 供派生goroutine查询用
*/

package main

import (
    "context"
    "log"
    "os"
    "time"
)

const (
    GOLABLE_KEY = "test123"
)

func main() {
    //父context控制子context
    controlAllConrrent()
}

func controlAllConrrent() {

    logg := log.New(os.Stdout,log.Ltime)
    handleSome()
    logg.Println("over ")
}

//父协程
func handleSome() {
    //ctx,cancelFunc := context.WithCancel(context.Background())
    //ctx,cancelFunc := context.WithTimeout(context.Background(),time.Second*2)
    ctx,cancelFunc := context.WithDeadline(context.Background(),time.Now().Add(time.Second*2))

    ctx = context.WithValue(ctx,GOLABLE_KEY,"1234")

    go workerFunc(ctx,"str1")
    go workerFunc(ctx,"str2")
    time.Sleep(time.Second * 3)
    cancelFunc()
}

//子协程
func workerFunc(ctx context.Context,showStr string) {
    for {
        time.Sleep(time.Second * 1)
        select {
        case <-ctx.Done():
            log.Println("done")
            return
        default:
            val123 := ctx.Value(GOLABLE_KEY).(string)
            log.Println(val123,showStr)
        }
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读