欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Golang如何監(jiān)聽某個函數(shù)的開始執(zhí)行和執(zhí)行結(jié)束

 更新時間:2024年02月05日 09:44:04   作者:vistart  
這篇文章主要為大家詳細介紹了Golang如何監(jiān)聽某個函數(shù)的開始執(zhí)行和執(zhí)行結(jié)束,文中的示例代碼講解詳細,有需要的小伙伴可以參考一下

如果想監(jiān)聽函數(shù)(方法)開始執(zhí)行和執(zhí)行結(jié)束,你需要設(shè)置兩個通道:

  • chanStarted: 用于發(fā)送開始執(zhí)行信號。
  • chanFinished: 用于發(fā)送執(zhí)行結(jié)束信號。

同時,為了保證監(jiān)聽方能實時得知“開始執(zhí)行”或“執(zhí)行結(jié)束”信號,需要在執(zhí)行任務(wù)前開啟監(jiān)聽。

以下為模擬監(jiān)聽函數(shù)(方法)開始執(zhí)行和執(zhí)行結(jié)束的示例:

package main

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

type Transit struct {
    worker       func(ctx context.Context, a ...any) (any, error)
    chanStarted  chan struct{}
    chanFinished chan struct{}
}

func (t *Transit) Run(ctx context.Context, a ...any) (any, error) {
    defer func() {
        t.chanFinished <- struct{}{}
    }()
    t.chanStarted <- struct{}{}
    return t.worker(ctx, a...)
}

func worker(ctx context.Context, a ...any) (any, error) {
    if timer, ok := a[0].(int); ok && timer > 0 {
        time.Sleep(time.Duration(timer) * time.Second)
    }
    return a[0], nil
}

func NewTransit() *Transit {
    return &Transit{
        worker:       worker,
        chanStarted:  make(chan struct{}),
        chanFinished: make(chan struct{}),
    }
}

func main() {
    transit := NewTransit()
    chanStarted := transit.chanStarted
    chanFinished := transit.chanFinished
    finished := make(chan struct{})
    go func() {
        for {
            select {
            case <-chanStarted:
                fmt.Println(time.Now(), "started.")
            case <-chanFinished:
                fmt.Println(time.Now(), "finished,")
                finished <- struct{}{}
                return
            default:
            }
        }
    }()
    run, _ := transit.Run(context.Background(), 0)
    <-finished
    fmt.Println(time.Now(), "result:", run)
}

上述方案中,必須設(shè)置監(jiān)聽方,否則Run()方法中會觸發(fā)死鎖。

如果想無阻塞的向通道發(fā)送,可以采取變通辦法,即提前登記事件接收方,產(chǎn)生事件時逐個發(fā)送。例如:

package main

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

type Transit struct {
    muListener sync.RWMutex
    listener   []TransitEventInterface

    worker func(ctx context.Context, a ...any) (any, error)
}

func (t *Transit) NotifyStarted() {
    for _, l := range t.listener {
        if l == nil {
            continue
        }
        l.NotifyStarted()
    }
}

func (t *Transit) NotifyFinished() {
    for _, l := range t.listener {
        if l == nil {
            continue
        }
        l.NotifyFinished()
    }
}

type TransitEventInterface interface {
    NotifyStarted()
    NotifyFinished()
}

type TransitEventListener struct {
    TransitEventInterface
}

var notifiedStarted = make(chan struct{})
var notifiedFinished = make(chan struct{})

func (l *TransitEventListener) NotifyStarted() {
    notifiedStarted <- struct{}{}
}

func (l *TransitEventListener) NotifyFinished() {
    notifiedFinished <- struct{}{}
}

func (t *Transit) Run(ctx context.Context, a ...any) (any, error) {
    t.muListener.RLock()
    defer t.muListener.RUnlock()
    t.NotifyStarted()
    defer t.NotifyFinished()
    return t.worker(ctx, a...)
}

func worker(ctx context.Context, a ...any) (any, error) {
    if timer, ok := a[0].(int); ok && timer > 0 {
        time.Sleep(time.Duration(timer) * time.Second)
    }
    return a[0], nil
}

func NewTransit() *Transit {
    return &Transit{
        worker:   worker,
        listener: []TransitEventInterface{&TransitEventListener{}},
    }
}

func main() {
    transit := NewTransit()
    finished := make(chan struct{})
    startedTime := time.Now()
    finishedTime := time.Now()
    go func() {
        for {
            select {
            case <-notifiedStarted:
                startedTime = time.Now()
            case <-notifiedFinished:
                finishedTime = time.Now()
                finished <- struct{}{}
                return
            default:
            }
        }
    }()
    run, _ := transit.Run(context.Background(), 0)
    <-finished
    fmt.Println(time.Now(), "result:", run)
    fmt.Println(finishedTime.Sub(startedTime))
}

由于 fmt.Println() 方法在向屏幕輸出內(nèi)容時采取非阻塞形式,因此,直接在接收信號處直接輸出會發(fā)現(xiàn)輸出“started.”和“finished.”的順序不固定。

為了保證盡可能精確測量開始和結(jié)束的時間差,建議采用上述記錄時間點并在結(jié)束后計算時間差的方式。

到此這篇關(guān)于詳解Golang如何監(jiān)聽某個函數(shù)的開始執(zhí)行和執(zhí)行結(jié)束的文章就介紹到這了,更多相關(guān)Go監(jiān)聽函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go中crypto/rsa庫的高效使用指南

    Go中crypto/rsa庫的高效使用指南

    本文主要介紹了Go中crypto/rsa庫的高效使用指南,從 RSA 的基本原理到 crypto/rsa 庫的實際應(yīng)用,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • go chan基本使用詳解

    go chan基本使用詳解

    本文主要介紹了go chan基本使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Golang中的錯誤處理的示例詳解

    Golang中的錯誤處理的示例詳解

    這篇文章主要為大家詳細介紹了Golang中的錯誤處理的相關(guān)資料,文章中的示例代碼講解詳細,對我們學(xué)習(xí)Golang有一定幫助,需要的可以參考一下
    2022-11-11
  • Golang發(fā)送http GET請求的示例代碼

    Golang發(fā)送http GET請求的示例代碼

    這篇文章主要介紹了Golang發(fā)送http GET請求的示例代碼,幫助大家更好的理解和使用golang,感興趣的朋友可以了解下
    2020-12-12
  • Go 語言json.Unmarshal 遇到的小問題(推薦)

    Go 語言json.Unmarshal 遇到的小問題(推薦)

    這篇文章主要介紹了 Go 語言json.Unmarshal 遇到的小問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • 一文帶你掌握Golang的反射基礎(chǔ)

    一文帶你掌握Golang的反射基礎(chǔ)

    go的反射是由其標(biāo)準(zhǔn)庫中的reflect包實現(xiàn),該reflect包實現(xiàn)了在運行時進行反射的能力,本篇主要介紹了reflect的常用的幾個方法,希望對大家有所幫助
    2023-02-02
  • grom設(shè)置全局日志實現(xiàn)執(zhí)行并打印sql語句

    grom設(shè)置全局日志實現(xiàn)執(zhí)行并打印sql語句

    本文主要介紹了grom設(shè)置全局日志實現(xiàn)執(zhí)行并打印sql語句,包括設(shè)置日志級別、實現(xiàn)自定義Logger接口以及如何使用GORM的默認logger,通過這些方法,可以更好地控制和記錄數(shù)據(jù)庫操作的日志信息
    2025-03-03
  • 獲取Golang環(huán)境變量的三種方式小結(jié)

    獲取Golang環(huán)境變量的三種方式小結(jié)

    本文介紹了Golang中獲取環(huán)境變量的三種方式,包含使用Viper包、GoDotEnv包和os包,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • go實現(xiàn)文件的創(chuàng)建、刪除與讀取示例代碼

    go實現(xiàn)文件的創(chuàng)建、刪除與讀取示例代碼

    這篇文章主要給大家介紹了關(guān)于go如何實現(xiàn)文件的創(chuàng)建、刪除與讀取的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧
    2019-02-02
  • Go?Ginrest實現(xiàn)一個RESTful接口

    Go?Ginrest實現(xiàn)一個RESTful接口

    這篇文章主要為大家介紹了Go?Ginrest實現(xiàn)一個RESTful接口示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08

最新評論