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)然,這需要一些同步。

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)槟MM可能快地進(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()
}

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。
- 3 回答
- 0 關(guān)注
- 247 瀏覽
添加回答
舉報(bào)