轮询API,将结果传递给chan,从chan传递到Websocket。恐慌

时间:2018-11-14 16:00:40

标签: go

我正在编写一个小程序包,每2秒向外部API发出一个GET请求。它从该请求中获取值并将其传递到通道。我已经将此频道提供给http.handler(chi路由器)使用,该频道升级到Websocket,前端将实时获取该值。恐慌错误有很多行,但我想最重要的是:

2018/11/14 16:47:55 http: response.WriteHeader on hijacked connection
2018/11/14 16:47:55 http: response.Write on hijacked connection

除此之外,我确信还有更好的方法可以做到这一点。有经验的Gophers那里有什么指针可以帮助像我这样的菜鸟改进它吗?

package currencyticker

import (
    "bitbucket.org/special/api/config"
    "encoding/json"
    "fmt"
    "github.com/go-chi/chi"
    "github.com/go-chi/render"
    "github.com/gorilla/websocket"
    "github.com/leekchan/accounting"
    "io/ioutil"
    "log"
    "math/big"
    "net/http"
    "time"
)

var (
    ac       = accounting.Accounting{Precision: 2}
    from     = "USD"
    to       = "EUR,SWK"
    url      = "https://min-api.currencyapi.com/data/price?fsym=" + from + "&tsyms=" + to
    messages = make(chan float64)
)

var wsupgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true // Disable CORS for testing
    },
}

// Config - init
type Config struct {
    *config.Config
}

type result map[string]float64

// New - init the configs
func New(configuration *config.Config) *Config {
    return &Config{configuration}
}

// Routes - api urls
func (config *Config) Routes() *chi.Mux {
    router := chi.NewRouter()
    router.Use(
        render.SetContentType(render.ContentTypeHTML), // Set content-Type headers as application/json
    )
    router.Get("/", config.GetPrice) // subscribe to new tweets

    return router
}

func (config *Config) GetPrice(w http.ResponseWriter, r *http.Request) {

    conn, err := wsupgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(fmt.Printf("Failed to set websocket upgrade: %+v ", err))
        return
    }

    for {
        time.Sleep(1 * time.Second)

        price := <-messages

        w, err := conn.NextWriter(websocket.TextMessage)
        if err != nil {
            fmt.Println("ws error", err)
        }
        currVal := ac.FormatMoneyBigFloat(big.NewFloat(price))

        if _, err := w.Write([]byte(currVal)); err != nil {
            fmt.Printf("w.Write() returned %v", err)
        }

        w.Close()

    }

}

// start getting the price of ether as soon as they ap starts
func init() {
    go startPollingPriceAPI()
}

// Go Routine to start polling
func startPollingPriceAPI() {
    for {
        time.Sleep(2 * time.Second)
        go getPriceFromAPI()
    }
}

func getPriceFromAPI() {

    w := http.Client{
        // Timeout: time.Second * 3,
    }

    req, _ := http.NewRequest(http.MethodGet, url, nil)

    res, err := w.Do(req)

    if err != nil {
        log.Println("err getting price [req]: ", err)
    }

    body, err := ioutil.ReadAll(res.Body)

    if err != nil {
        log.Println("err getting price [io-read]: ", err)
    }

    r := result{}

    if jsonErr := json.Unmarshal(body, &r); jsonErr != nil {
        log.Println("err getting price [json]: ", jsonErr)
    }
    fmt.Println("1 Dollar = €", r["EUR"])

    messages <- r["EUR"]

}

0 个答案:

没有答案