如何平均JSON数组的值,然后舍入到小数点后1位

I'm new to Go and can't figure out how to simply read and average the values of an array of JSONs. I also want to round my result to 1 decimal point, but Go has no Round() function. Here's the data:

[
    {"millisUTC":"1496424000000","price":"7.6"},
    {"millisUTC":"1496423700000","price":"7.5"},
    {"millisUTC":"1496423400000","price":"9.1"},
    {"millisUTC":"1496423100000","price":"9.2"},
    {"millisUTC":"1496422800000","price":"10.0"}
]

I want to get the prices and average them, rounding to 1 decimal point. Yet it took me over 30 lines of code, when (as a Ruby developer) it would usually take me 3 lines. How do I simplify this? My code takes in 2 parameters, starttime and endtime, and calls an API: https://github.com/rayning0/griddy/blob/master/controllers/default.go

type arrayOfMaps []map[string]string

func getAvgPrice(starttime, endtime string) float64 {
    response, err := http.Get("https://hourlypricing.comed.com/api?type=5minutefeed&datestart=" + starttime + "&dateend=" + endtime)

   if err != nil {
        fmt.Println(err)
    }
    defer response.Body.Close()

    energyJSON, err := ioutil.ReadAll(response.Body)
    if err != nil {
        fmt.Println(err)
    }

    var energyPrices arrayOfMaps
    err = json.Unmarshal(energyJSON, &energyPrices)

    fmt.Println("Energy prices between", starttime, "and", endtime)
    fmt.Println(energyPrices)

    var sum float64
    var size int
    for _, p := range energyPrices {
        price, _ := strconv.ParseFloat(p["price"], 64)
        sum += price
        size++
    }
    avg := Truncate(sum / float64(size))
    fmt.Println("Average price:", avg)
    return avg
}

//Truncate a float to 1 level of precision
func Truncate(some float64) float64 {
    return float64(int(some*10)) / 10
}

Edited, thanks to excellent help from @icza!

This applies to my question: https://golang.org/pkg/encoding/json/#Decoder.Decode

See my revised solution, with detailed comments: https://github.com/rayning0/griddy/blob/master/controllers/default.go

Your code can be simplified in several points, and while you said "rounding" you did "truncating" in the end which is not the same.

One important thing: if an error is encountered, you should return early and not continue, as that will only be the source of additional errors or even runtime panics. See at the end.

Unmarshaling JSON

Easier would be to use json.Decoder, decoding right from the response body (which implements io.Reader).

Also note to simplify parsing floats given as string values in JSON, a better option would be to use json.Number.

Parsing can be as simple as this:

var prices []map[string]json.Number
if err := json.NewDecoder(response.Body).Decode(&prices); err != nil {
    fmt.Println(err)
    return
}

Calculating sum

Calculating sum can also be simplified: there is no need to keep track of size, as that is simply the length of the map:

sum := 0.0
for _, p := range prices {
    f, _ := p["price"].Float64()
    sum += f
}

Note that if you want to handle errors in a way to simply exclude it from the sum (and not return with an error), only then would you need to count valid numbers.

Rounding

Multiplying by 10 and then dividing by 10 is truncating and not rounding. For rounding, you should add 0.5 between those 2 operations. For details, see this answer: Golang Round to Nearest 0.05

So a correct rounding function that properly rounds both positive and negative numbers to arbitrary unit:

func Round(x, unit float64) float64 {
    if x > 0 {
        return float64(int64(x/unit+0.5)) * unit
    }
    return float64(int64(x/unit-0.5)) * unit
}

So the result:

avg := Round(sum/float64(len(prices)), 0.1)

The complete solution with error handling

Since your getAvgPrice() can fail at multiple points, you should definitely add an error return value too.

This is the complete solution with proper error handling:

func getAvgPrice(starttime, endtime string) (float64, error) {
    response, err := http.Get("https://hourlypricing.comed.com/api?type=5minutefeed&datestart=" + starttime + "&dateend=" + endtime)
    if err != nil {
        return 0, err
    }
    defer response.Body.Close()

    var prices []map[string]json.Number
    if err := json.NewDecoder(response.Body).Decode(&prices); err != nil {
        return 0, err
    }

    sum := 0.0
    for _, p := range prices {
        f, err := p["price"].Float64()
        if err != nil {
            return 0, err
        }
        sum += f
    }

    return Round(sum/float64(len(prices)), 0.1), nil
}