第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

Go:通過通道傳遞函數(shù)

Go:通過通道傳遞函數(shù)

Go
拉丁的傳說 2021-12-06 19:41:42
我試圖通過將我調(diào)用的函數(shù)放置在稍后訪問的隊(duì)列中來對(duì)它們進(jìn)行速率限制。下面我有一段我創(chuàng)建的請(qǐng)求,requestHandler 函數(shù)以一定的速率處理每個(gè)請(qǐng)求。我希望它接受具有不同類型參數(shù)的各種函數(shù),因此是 interface{} 類型。我如何才能通過通道傳遞函數(shù)并成功調(diào)用它們?type request struct {    function interface{}    channel  chan interface{}}var requestQueue []requestfunc pushQueue(f interface{}, ch chan interface{}) {    req := request{        f,        ch,    }    //push    requestQueue = append(requestQueue, req)}func requestHandler() {    for {        if len(requestQueue) > 0 {            //pop            req := requestQueue[len(requestQueue)-1]            requestQueue = requestQueue[:len(requestQueue)-1]            req.channel <- req.function        }        <-time.After(1200 * time.Millisecond)    }}這是我想要實(shí)現(xiàn)的示例(GetLeagueEntries(string, string) 和 GetSummonerName(int, int) 是函數(shù)):ch := make(chan interface{})    pushQueue(l.GetLeagueEntries, ch)    pushQueue(l.GetSummonerName, ch)    leagues, _ := <-ch(string1, string2)    summoners, _ := <-ch(int1, int2)
查看完整描述

3 回答

?
侃侃無極

TA貢獻(xiàn)2051條經(jīng)驗(yàn) 獲得超10個(gè)贊

首先,我會(huì)把它寫成:


leagues := server.GetLeagueEntries()

summoners := server.GetSummoners()

并且,將速率限制放入服務(wù)器。使用速率限制庫之一。


但是,可以使用接口來統(tǒng)一請(qǐng)求,并使用 func 類型來允許閉包(如在 http.HandleFunc 中):


type Command interface {

    Execute(server *Server)

}


type CommandFunc func(server *Server)

func (fn CommandFunc) Execute(server *Server) { fn(server) }


type GetLeagueEntries struct { Leagues []League }


func (entries *GetLeagueEntries) Execute(server *Server) {

    // ...

}


func GetSummonerName(id int, result *string) CommandFunc {

    return CommandFunc(func(server *Server){

        *result = "hello"

    })

}


get := GetLeagueEnties{}

requests <- &get


requests <- CommandFunc(func(server *Server){

    // ... handle struff here

})

當(dāng)然,這需要一些同步。


查看完整回答
反對(duì) 回復(fù) 2021-12-06
?
當(dāng)年話下

TA貢獻(xiàn)1890條經(jīng)驗(yàn) 獲得超9個(gè)贊

好的,這是代碼:https : //play.golang.org/p/XZvb_4BaJF


請(qǐng)注意,它并不完美。您有一個(gè)每秒執(zhí)行一次的隊(duì)列。如果隊(duì)列為空并且添加了新項(xiàng)目,則新項(xiàng)目可以等待近一秒鐘才能執(zhí)行。


但這應(yīng)該讓你非常接近你需要的東西:)


此代碼可以分為 3 部分:


限速隊(duì)列執(zhí)行器,我稱之為服務(wù)器(我很擅長命名)——服務(wù)器對(duì)這些功能一無所知。它所做的就是啟動(dòng)一個(gè)永無止境的 goroutine,每秒彈出一次隊(duì)列中最舊的函數(shù),并調(diào)用它。我上面談到的問題在代碼的這一部分 BTW,如果您愿意,我可以幫助您修復(fù)它。

按鈕單擊功能 - 這向您展示了每次單擊按鈕如何使用服務(wù)器調(diào)用 3 個(gè)差異函數(shù)(您顯然可以進(jìn)行更多/更少的函數(shù)調(diào)用),并確保它們彼此相隔 1 秒。您甚至可以為任何函數(shù)添加超時(shí)(以偽造延遲),它們?nèi)匀粫?huì)相隔 1 秒被調(diào)用。這是唯一需要通道的地方,因?yàn)槟MM可能快地進(jìn)行所有函數(shù)調(diào)用(如果第一個(gè)函數(shù)需要 5 秒,則您只想等待 1 秒來調(diào)用第二個(gè)函數(shù))然后等待它們完成,所以你需要知道它們什么時(shí)候完成。

按鈕點(diǎn)擊模擬(主要功能) - 這只是表明 3 次按鈕點(diǎn)擊會(huì)按預(yù)期工作。你也可以把它們放在一個(gè) goroutine 中來模擬 3 個(gè)用戶同時(shí)點(diǎn)擊按鈕,它仍然可以工作。


package main


import (

    "fmt"

    "sync"

    "time"

)


const (

    requestFreq = time.Second

)


type (

    // A single request

    request func()


    // The server that will hold a queue of requests and make them once a requestFreq

    server struct {

        // This will tick once per requestFreq

        ticker     *time.Ticker


        requests []request

        // Mutex for working with the request slice

        sync.RWMutex

    }

)


var (

    createServerOnce sync.Once

    s *server

)


func main() {

    // Multiple button clicks:

    ButtonClick()

    ButtonClick()

    ButtonClick()


    fmt.Println("Done!")

}







// BUTTON LOGIC:


// Calls 3 functions and returns 3 diff values.

// Each function is called at least 1 second appart.

func ButtonClick() (val1 int, val2 string, val3 bool) {

    iCh := make(chan int)

    sCh := make(chan string)

    bCh := make(chan bool)


    go func(){

        Server().AppendRequest(func() {

            t := time.Now()

            fmt.Println("Calling func1 (time: " + t.Format("15:04:05") + ")")

            // do some stuff

            iCh <- 1

        })

    }()

    go func(){

        Server().AppendRequest(func() {

            t := time.Now()

            fmt.Println("Calling func2 (time: " + t.Format("15:04:05") + ")")

            // do some stuff

            sCh <- "Yo"

        })

    }()

    go func(){

        Server().AppendRequest(func() {

            t := time.Now()

            fmt.Println("Calling func3 (time: " + t.Format("15:04:05") + ")")

            // do some stuff

            bCh <- true

        })

    }()


    // Wait for all 3 calls to come back

    for count := 0; count < 3; count++ {

        select {

        case val1 = <-iCh:

        case val2 = <-sCh:

        case val3 = <-bCh:

        }

    }


    return

}






// SERVER LOGIC


// Factory function that will only create a single server

func Server() *server {

    // Only one server for the entire application

    createServerOnce.Do(func() {

        s = &server{ticker: time.NewTicker(requestFreq), requests: []request{}}


        // Start a thread to make requests.

        go s.makeRequests()

    })

    return s

}

func (s *server) makeRequests() {

    if s == nil || s.ticker == nil {

        return

    }


    // This will keep going once per each requestFreq

    for _ = range s.ticker.C {


        var r request


        // You can't just access s.requests because you are in a goroutine

        // here while someone could be adding new requests outside of the 

        // goroutine so you have to use locks.

        s.Lock()

        if len(s.requests) > 0 {

            // We have a lock here, which blocks all other operations 

            // so just shift the first request out, save it and give 

            // the lock back before doing any work.

            r = s.requests[0]

            s.requests = s.requests[1:]

        }

        s.Unlock()


        if r != nil {

            // make the request!

            r()

        }

    }

}

func (s *server) AppendRequest(r request) {

    if s == nil {

        return

    }

    s.Lock()

    s.requests = append(s.requests, r)

    s.Unlock()

}


查看完整回答
反對(duì) 回復(fù) 2021-12-06
?
慕神8447489

TA貢獻(xiàn)1780條經(jīng)驗(yàn) 獲得超1個(gè)贊

我原以為使用某種信號(hào)量或工作池更容易。這樣,您可以做任何事情的工人數(shù)量有限。也可以有多個(gè)工作池。

您是否需要這些調(diào)用中的任何一個(gè)是并發(fā)/異步的?如果沒有,它們可以被調(diào)用,以便你可以有可配置的睡眠(一個(gè)討厭的黑客頭腦)。

嘗試工作池或信號(hào)量而不是函數(shù)的 chan。


查看完整回答
反對(duì) 回復(fù) 2021-12-06
  • 3 回答
  • 0 關(guān)注
  • 247 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)