dongwen9051 2018-05-11 10:40
浏览 101
已采纳

去不立即响应GET请求,完成报价后立即响应

I'm new to Go programming and I try to build API for a multiplayer game. If I make GET req to the http://localhost:8080/create_game/gameName . Server response to the request when ticker is done. I need to get response from a server instantly but I got it when ticker is over and game is timeouted and deleted.

Here is my code:

var clients = make(map[*websocket.Conn]bool)
var broadcast = make(chan Game)

//GAME_TIMEOUT in seconds
const GAME_TIMEOUT = 20

//ID generating
var genID = 0

var games = []Game{}

var msg json.RawMessage

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

type GameToSend struct {
    Type string `json:"type"`
    ID   int    `json:"id"`
    Name string `json:"name"`
}
type Game struct {
    ID    int              `json:"id"`
    Name  string           `json:"name"`
    Timer <-chan time.Time `json:"timestamp"`
}

func main() {
    router := mux.NewRouter()
    router.HandleFunc("/create_game/{name}", createGame)
    router.HandleFunc("/game_events", handleConnections)
    http.ListenAndServe(":8080", router)
}

func handleConnections(w http.ResponseWriter, r *http.Request) {

    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    clients[conn] = true
    for _, game := range games {
        conn.WriteJSON(GameToSend{"game.created", game.ID, game.Name})
    }
    for {
        err := conn.ReadJSON(&msg)
        if err != nil {
            fmt.Println(err)
        } else {
            fmt.Println(msg)
        }
    }
}

func broadcastGame(game GameToSend) {
    for conn := range clients {
        conn.WriteJSON(game)
    }
}

func createGame(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    genID++
    game := Game{genID, params["name"], time.NewTimer(GAME_TIMEOUT * time.Second).C}
    games = append(games, game)
    broadcastGame(GameToSend{"game.created", game.ID, game.Name})
    w.Write([]byte("response"))
    checkTimeout(genID)
}

func deleteGame(actionType string, i int) {
    for index, game := range games {
        if game.ID == i {
            broadcastGame(GameToSend{actionType, games[index].ID, games[index].Name})
            games = games[:index+copy(games[index:], games[index+1:])]
        }
    }
}

func checkTimeout(id int) {
    for _, game := range games {
        if game.ID == id {
            <-game.Timer
            deleteGame("game.timeout", id)
        }
    }
}

any idea how to fix it?

  • 写回答

1条回答 默认 最新

  • dtkl55257 2018-05-11 11:22
    关注

    There are a number of things you could change, but one of them is in general don't run potentially long running tasks in the code that is responding to clients. Imagine you have millions of games, so many that each call to checkTimeout takes a second to iterate over all the games. Every request would have a one second delay to get a complete response, not great. It would be better to signal another goroutine should iterate over the games and clean up expired ones, that way you can return immediately to the client while the clean up happens in the background.

    Turns out I misread what you are doing, but the advice is still valid. In this case though the "long running function" actually waits until the timer expires before returning. That could be significantly longer than one second! Were you meaning to run that in a goroutine? go checkTimeout(genID)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 实验 :UML2.0 行为建模
  • ¥15 设计一种优化调度算法并结合论文中的案例给出调度计划
  • ¥15 py文件打包exe报错TypeError:expected str,bytes or os.PathLike object,not_io.BytesIO
  • ¥15 Java编写学籍信息管理系统
  • ¥15 IPXE网刻客户机找不到服务端
  • ¥15 小贝360-4 配二个 华772S 设置WⅰFi5G 连接
  • ¥15 vs2022的QT报错,好像是缺少winextras
  • ¥15 怎么看 cst中一个面的功率分布图
  • ¥15 c语言数据结构求9999
  • ¥15 Fiddler无法对部分小程序抓包