鍍金池/ 問答/GO  HTML/ golang中對time.NewTicker()返回的指針取值后調(diào)用Stop無法

golang中對time.NewTicker()返回的指針取值后調(diào)用Stop無法停止ticker

圖片描述

如圖所示,代碼不長,tickerTest1中對Ticker指針取值以后Stop沒有反應(yīng),tickerTest2直接用返回的指針則沒有任何問題。

回答
編輯回答
安若晴

v2 = *p1 將產(chǎn)生新的結(jié)構(gòu)體 v2,它的值由 p1 指針?biāo)傅慕Y(jié)構(gòu)體復(fù)制而來。

因此,你在 tickerTest2() 中調(diào)用的 ticker.Stop() 并不是 time.NewTicker() 創(chuàng)建的那個,而是復(fù)制品。

舉個例子參考下

package main

import (
    "testing"
)

func Test_dereference_pointer(t *testing.T) {
    type Foo struct {
        N int
    }

    p1 := &Foo{1}
    f2 := *p1 // 將 p1 克隆成新的結(jié)構(gòu)體 f2,不是引用

    p1.N = 2
    f2.N = 3

    if p1.N != 2 || f2.N != 3 {
        t.Fatal("error")
    }
}
2018年8月19日 10:39
編輯回答
悶騷型

翻了下 runtime 包,發(fā)現(xiàn)在 stop 的時候有這么一個判斷 :

if i < 0 || i > last || tb.t[i] != t {
    return false
}

關(guān)鍵在于 tb.t[i] != t。如 @李毅 所說,如果使用 tick := *time.NewTicker(time.Second) 是復(fù)制了一份,則這個條件肯定為真,即不釋放該計時器資源,相當(dāng)于沒有 stop。所以計時器沒有停止。


大家都需要注意的是:不要對 Ticker.C 使用 range,因為在調(diào)用 Ticker.Stop 的時候并不會 close 該 channel,所以這里相當(dāng)于一個死循環(huán)。

2017年6月4日 07:17