duanhuantong8278 2015-06-19 15:17
浏览 22
已采纳

for循环中的goroutine通道

My main function reads json from a file, unmarshals it into a struct, converts it into another struct type and spits out formatted JSON through stdout.

I'm trying to implement goroutines and channels to add concurrency to my for loop.

func main() {
    muvMap := map[string]string{"male": "M", "female": "F"}
    fileA, err := os.Open("serviceAfileultimate.json")
    if err != nil {
        panic(err)
    }
    defer fileA.Close()

    data := make([]byte, 10000)
    count, err := fileA.Read(data)
    if err != nil {
        panic(err)
    }

    dataBytes := data[:count]

    var servicesA ServiceA
    json.Unmarshal(dataBytes, &servicesA)
    var servicesB = make([]ServiceB, servicesA.Count)
    goChannels := make(chan ServiceB, servicesA.Count)

    for i := 0; i < servicesA.Count; i++ {
        go func() {
            reflect.ValueOf(&servicesB[i]).Elem().FieldByName("Address").SetString(Merge(&servicesA.Users[i].Location))
            reflect.ValueOf(&servicesB[i]).Elem().FieldByName("Date_Of_Birth").SetString(dateCopyTransform(servicesA.Users[i].Dob))
            reflect.ValueOf(&servicesB[i]).Elem().FieldByName("Email").SetString(servicesA.Users[i].Email)
            reflect.ValueOf(&servicesB[i]).Elem().FieldByName("Fullname").SetString(Merge(&servicesA.Users[i].Name))
            reflect.ValueOf(&servicesB[i]).Elem().FieldByName("Gender").SetString(muvMap[servicesA.Users[i].Gender])
            reflect.ValueOf(&servicesB[i]).Elem().FieldByName("Phone").SetString(servicesA.Users[i].Cell)
            reflect.ValueOf(&servicesB[i]).Elem().FieldByName("Username").SetString(servicesA.Users[i].Username)
            goChannels <- servicesB[i]
        }()
    }

    for index := range goChannels {
        json.NewEncoder(os.Stdout).Encode(index)
    }

}

It compiles but is returning messages like:

goroutine 1 [chan receive]: main.main() C://.....go.94 +0x55b.
  • 写回答

1条回答 默认 最新

  • douleng0794 2015-06-19 18:12
    关注

    You're printing the channels info, not the data it contains. You don't want a loop, you just want to receive then print.

       json := <-index
       json.NewEncoder(os.Stdout).Encode(json)
    

    Now I do I need to point out, that code is not going to block. If you want to keep reading until all work is done you need some kind of locking/coordination mechanism.

    You'll often see things like

    for {
       select {
            case json := <-jsonChannel:
                // do stuff
            case <-abort:
                // get out of here 
       }
    }
    

    To deal with that. Also, just fyi you're initializing your channel with a default capacity (meaning it's a buffered channel) which is pretty odd. I'd recommend reviewing some tutorials on the topic cause overall your design needs some work actually be an improvement of non-concurrent implementations. Lastly you can find libraries to abstract some of this work for you and most people would probably recommend you do. Here's an example; https://github.com/lytics/squaredance

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

报告相同问题?

悬赏问题

  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题