2015-06-19 64 views
0

我的main函數從文件讀取json,將它解組爲一個結構,將它轉換爲另一個結構類型並通過stdout將格式化的JSON吐出。goroutine頻道over for循環

我正在嘗試執行goroutines和通道來爲我的for循環添加併發。

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) 
    } 

} 

它編譯但返回的信息一樣:

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

回答

1

要打印的信道信息,而不是它包含的數據。你不想要一個循環,你只想接收然後打印。

​​

現在我需要指出的是,該代碼不會阻止。如果你想繼續閱讀,直到完成所有工作,你需要某種鎖定/協調機制。

你會經常看到像

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

爲了解決這個問題。另外,只要你使用默認容量初始化你的頻道(意味着它是一個緩衝頻道),這很奇怪。我建議查看關於該主題的一些教程,因爲總體而言,您的設計需要一些工作實際上是對非並行實現的改進。最後,你可以找到圖書館爲你抽出一些這項工作,大多數人可能會建議你這樣做。這是一個例子。 https://github.com/lytics/squaredance

+0

謝謝你的回覆,埃文。我選擇使用緩衝通道,因爲我需要轉換和打印多個結構。沒有緩衝渠道,我該怎麼做? –

+0

@ScottS。你可以爲這些目的使用一個數組。渠道的想法是提供工作線程和應用程序層之間的通信,您可以使用緩衝區,這很少完成,並稍微改變它們的機制。通常情況下,一個通道阻塞,直到它讀取,所以你會使用一個for循環,就像我上面的循環一樣,直到goroutine說它完成了,或者你從其他地方得到關閉或中止類型的信號時,才繼續讀取通道。 – evanmcdonnal

+0

如果你打算使用一個緩衝通道來放入一個完整的數組,那麼你可能根本就不使用goroutine,只是使用阻塞呼叫,因爲在那個時候你不會傳輸數據,只是在不做任何事情的情況下進行異步準備,而是等待它完成。 – evanmcdonnal