Go 在选择{case:channel}中更改频道

Go 在选择{case:channel}中更改频道,go,channel,Go,Channel,我使用一个Ticker定期执行任务,但在更改它时遇到了一些问题。收到一些消息后,我会将股票代码更改为新的,并更改时间间隔。下面是将重新处理此问题的示例代码: package main import ( "fmt" "time" ) type A struct { ticker *time.Ticker } func (a *A) modify() { a.ticker.Stop() a.ticker = time.NewTicker(time.Sec

我使用一个Ticker定期执行任务,但在更改它时遇到了一些问题。收到一些消息后,我会将股票代码更改为新的,并更改时间间隔。下面是将重新处理此问题的示例代码:

package main

import (
    "fmt"
    "time"
)

type A struct {
    ticker *time.Ticker
}

func (a *A) modify() {
    a.ticker.Stop()
    a.ticker = time.NewTicker(time.Second)
}
func main() {
    a := new(A)
    a.ticker = time.NewTicker(time.Second)
    go func() {
        for {
            select {
            case <-a.ticker.C:
                fmt.Println("now")
                go a.modify()
                /*
                    default:
                        //fmt.Println("default")
                        time.Sleep(time.Millisecond * 100)
                */
            }
        }
    }()
    time.Sleep(time.Second * 60)
}
主程序包
进口(
“fmt”
“时间”
)
类型A结构{
ticker*time.ticker
}
func(a*a)modify(){
a、 股票代码停止()
a、 ticker=time.NewTicker(time.Second)
}
func main(){
a:=新的(a)
a、 ticker=time.NewTicker(time.Second)
go func(){
为了{
挑选{

case问题在于goroutine是异步运行的。 使用
a.modify()
时,代码的行为如下:

  • a.ticker.C
  • 停止旧的ticker,并创建新的
    a.ticker.C
  • 使用
    选择
  • 在这种情况下,2.中新创建的
    a.ticker.C
    与3.中的频道等待相同

    如果你在goroutine中做2。它可以按照以下顺序进行

  • a.ticker.C
  • 使用
    选择
  • 停止旧的ticker,并创建新的
    a.ticker.C
  • 在这种情况下,2.中等待的通道与3.中新创建的通道不同。 由于选择频道是一个被停止的旧频道,所以它永远不会得到任何滴答声

    您可以通过插入一些
    fmt.Printf
    来确认此行为,并查看
    a.ticker.C
    的地址

    func (a *A) modify() {
        a.ticker.Stop()
        fmt.Printf("ticker stopped: %p\n", &a.ticker.C)
        a.ticker = time.NewTicker(time.Second)
        fmt.Printf("new ticker created: %p\n", &a.ticker.C)
    }
    func main() {
        a := new(A)
        a.ticker = time.NewTicker(time.Second)
        go func() {
            for {
                fmt.Printf("waiting for ticker: %p\n", &a.ticker.C)
                select {
            ....
    
    使用
    a.modify()

    使用
    转到a.modify()

    您可以看到,使用
    go a.modify()
    时,您并不是在等待新创建的频道

    默认行为的更新:

    默认值:
    go a.modify()
    一起使用时,其行为如下

  • 等待
    a.ticker.C
    ,打勾,调用
    go a.modify()
    ,它执行3
  • 等待
    a.ticker.C
    ,什么也得不到,所以返回默认值并睡眠100毫秒
  • 停止旧的ticker,更新
    a.ticker.C
  • 等待
    a.ticker.C
    ,什么也得不到,所以返回默认值并睡眠100毫秒
  • 等待
    a.ticker.C
    ,什么也得不到,所以返回默认值并睡眠100毫秒
  • 等待
    a.ticker.C
    ,什么也得不到,所以返回默认值并睡眠100毫秒
  • 等待
    a.ticker.C
    ,打勾,调用
    go a.modify()
  • 关键是,{}
    循环可以继续进行,即使您从
    a.ticker.C
    中什么都没有得到。 您可以使用相同的代码确认该行为

    waiting ticker: 0xc420010100     <-- 1.
    now                              <-- 1.
    waiting ticker: 0xc420010100     <-- 2.
    default                          <-- 2.
    ticker stopped: 0xc420010100     <-- 3.
    new ticker created: 0xc420066240 <-- 3.
    waiting ticker: 0xc420066240     <-- 4.
    default                          <-- 4.
    

    waiting ticker:0xc420010100明白了!那么为什么默认情况也可以解释一下
    
    waiting for ticker: 0xc420010100
    ticker stopped: 0xc420010100
    new ticker created: 0xc420068000
    waiting for ticker: 0xc420068000
    ticker stopped: 0xc420068000
    new ticker created: 0xc420068080
    waiting for ticker: 0xc420068080
    
    waiting for ticker: 0xc420010100
    waiting for ticker: 0xc420010100
    ticker stopped: 0xc420010100
    new ticker created: 0xc420066040
    
    waiting ticker: 0xc420010100     <-- 1.
    now                              <-- 1.
    waiting ticker: 0xc420010100     <-- 2.
    default                          <-- 2.
    ticker stopped: 0xc420010100     <-- 3.
    new ticker created: 0xc420066240 <-- 3.
    waiting ticker: 0xc420066240     <-- 4.
    default                          <-- 4.