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

I'm writing a small package which does a GET request to an external API every 2 seconds. It takes the value from this request and passes it into a channel. I have made this channel available to a http.handler (chi router) which upgrades to a websocket where the front-end will grab the value in realtime. the panic error is a lot of lines but i guess the most important is this:

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

Aside from that I'm sure there is a better way of doing this. Any experienced Gophers out there have any pointers to help a noob such as myself improve this?

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"]

}