请问如何处理channel里的json数据?

package main

import (
    //    "bytes"
    //    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "time"

    "github.com/jeremywohl/flatten"
)

type item struct {
    Endpoint    string `json:"endpoint"`
    Metric      string `json:"metric"`
    Timestamp   int64  `json:"timestamp"`
    Step        int    `json:"step"`
    Value       int64  `json:"value"`
    CounterType string `json:"counterType"`
    Tags        string `json:"tags"`
}

type message struct {
    Item []item `json:"item"`
}

func getItem(m string, value int64) *message {
    var v item
    hostName, _ := os.Hostname()
    v.Endpoint = hostName
    v.Timestamp = time.Now().Unix()
    v.Step = 60
    v.CounterType = "counter"
    v.Tags = "service=get_stats"
    //v.Item = append(v.Item, item{Endpoint: hostName, Metric: m, Timestamp: time.Now().Unix(), Step: 10, Value: value})
    var o message
    o.Item = append(o.Item, v)
    return &o
}

func getMetric(url string, ch chan<- *string) {
    resp, err := http.Get(url)
    if err != nil || resp.StatusCode != 200 {
        ch <- nil
        return
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        ch <- nil
        return
    }
    b := string(body)
    flat, err := flatten.FlattenString(b, "", flatten.DotStyle)
    if err == nil {
        ch <- &flat
        return
    }
}

func main() {
    ch := make(chan *string)
    for _, i := range []int{9010, 9011} {
        go getMetric(fmt.Sprintf("http://127.0.0.1:%d/stats", i), ch)
    }
    for i := 0; i <= 2; i++ {
        r := <-ch
        fmt.Printf("%v", *r)
    }
}

大家好,我是个编程新手,我的问题是从两个端口获得了两个结构一样的json串,放在了channel里,想求出相同key对应value的平均值,放在一个map里,请问我改怎么继续操作?channel里的内容如下:
{"/.concurrent":37,"/.memory.external":78169527,"/.memory.heapTotal":27561984,"/.memory.heapUsed":22119416,"/.memory.rss":116285440,"/.response time.count":0,"/.response time.max":null,"/.response time.mean":0,"/.response time.median":null,"/.response time.min":null,"/.response time.p75":null,"/.response time.p95":null,"/.response time.p99":null,"/.response time.p999":null,"/.response time.stddev":null,"/.response time.sum":0,"/.response time.variance":null,"/.rps.15MinuteRate":0.00012075894874869729,"/.rps.1MinuteRate":5.436038710777194e-22,"/.rps.5MinuteRate":5.796628121959268e-7,"/.rps.count":37,"/.rps.currentRate":0.0003710280299097369,"/.rps.mean":0.00024527526450522207,"/.uptime":174990.967,"/stats.concurrent":37,"/stats.response time.count":0,"/stats.response time.max":null,"/stats.response time.mean":0,"/stats.response time.median":null,"/stats.response time.min":null,"/stats.response time.p75":null,"/stats.response time.p95":null,"/stats.response time.p99":null,"/stats.response time.p999":null,"/stats.response time.stddev":null,"/stats.response time.sum":0,"/stats.response time.variance":null,"/stats.rps.15MinuteRate":0.00012075894874869729,"/stats.rps.1MinuteRate":5.436038710777194e-22,"/stats.rps.5MinuteRate":5.796628121959268e-7,"/stats.rps.count":37,"/stats.rps.currentRate":0.00037102803025777217,"/stats.rps.mean":0.00024527526372303265}{"/.concurrent":40,"/.memory.external":78169527,"/.memory.heapTotal":27561984,"/.memory.heapUsed":21506496,"/.memory.rss":111173632,"/.response time.count":0,"/.response time.max":null,"/.response time.mean":0,"/.response time.median":null,"/.response time.min":null,"/.response time.p75":null,"/.response time.p95":null,"/.response time.p99":null,"/.response time.p999":null,"/.response time.stddev":null,"/.response time.sum":0,"/.response time.variance":null,"/.rps.15MinuteRate":0.00012114021669426971,"/.rps.1MinuteRate":5.905986428647385e-22,"/.rps.5MinuteRate":5.868342501095499e-7,"/.rps.count":40,"/.rps.currentRate":0.00037102786749615034,"/.rps.mean":0.0002532938745184385,"/.uptime":174991.285,"/stats.concurrent":40,"/stats.response time.count":0,"/stats.response time.max":null,"/stats.response time.mean":0,"/stats.response time.median":null,"/stats.response time.min":null,"/stats.response time.p75":null,"/stats.response time.p95":null,"/stats.response time.p99":null,"/stats.response time.p999":null,"/stats.response time.stddev":null,"/stats.response time.sum":0,"/stats.response time.variance":null,"/stats.rps.15MinuteRate":0.00012114021669426971,"/stats.rps.1MinuteRate":5.905986428647385e-22,"/stats.rps.5MinuteRate":5.868342501095499e-7,"/stats.rps.count":40,"/stats.rps.currentRate":0.00037102786713249256,"/stats.rps.mean":0.00025329387411713873}
已邀请:

dncmn - 90it男

赞同来自:

能转换成map进行操作吗?

anoymouswho

赞同来自:

json字符串可以直接写到map里面 statsMap := make(map[string]interface{}) err := json.Unmarshal([]byte(*r), &statsMap)

qiyin

赞同来自:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "time"

    "github.com/jeremywohl/flatten"
    "github.com/thinkeridea/go-extend/exbytes"
    "github.com/thinkeridea/go-extend/exstrings"
)

type item struct {
    Endpoint    string `json:"endpoint"`
    Metric      string `json:"metric"`
    Timestamp   int64  `json:"timestamp"`
    Step        int    `json:"step"`
    Value       int64  `json:"value"`
    CounterType string `json:"counterType"`
    Tags        string `json:"tags"`
}

type message struct {
    Item []item `json:"item"`
}

func getItem(m string, value int64) *message {
    var v item
    hostName, _ := os.Hostname()
    v.Endpoint = hostName
    v.Timestamp = time.Now().Unix()
    v.Step = 60
    v.CounterType = "counter"
    v.Tags = "service=get_stats"
    //v.Item = append(v.Item, item{Endpoint: hostName, Metric: m, Timestamp: time.Now().Unix(), Step: 10, Value: value})
    var o message
    o.Item = append(o.Item, v)
    return &o
}

func getMetric(url string, ch chan<- string) {
    resp, err := http.Get(url)
    if err != nil || resp.StatusCode != 200 {
        ch <- ""
        return
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        ch <- ""
        return
    }
    b := exbytes.ToString(body)
    flat, err := flatten.FlattenString(b, "", flatten.DotStyle)
    if err == nil {
        ch <- flat
        return
    }
}

type converge struct {
    Sum float64
    Num int
}

func main() {
    ch := make(chan string)
    for _, i := range []int{9010, 9011} {
        go getMetric(fmt.Sprintf("http://127.0.0.1:%d/stats", i), ch)
    }

    converges := map[string]*converge{}
    for i := 0; i < 2; i++ {

        r := <-ch
        if r == "" {
            continue
        }

        data := make(map[string]*float64, 100)
        err := json.Unmarshal(exstrings.UnsafeToBytes(r), &data)
        if err != nil {
            panic(err)
        }

        for k, v := range data {
            if _, ok := converges[k]; !ok {
                converges[k] = &converge{}
            }

            converges[k].Num++
            if v != nil {
                converges[k].Sum += *v
            }
        }
    }

    avg := map[string]float64{}
    for k, v := range converges {
        avg[k] = v.Sum / float64(v.Num)
    }

    fmt.Println(avg)
}

简略的实现,并不是最优的代码,不建议使用 chan *string, 字符串传递的代价非常的小,使用指针反而会给GC带来更大的压力

要回复问题请先登录注册