2015-06-19 2 views
0

Функция main считывает json из файла, разворачивает ее в структуру, преобразует ее в другой тип структуры и выплескивает форматированный JSON через stdout.goroutine channels over a for loop

Я пытаюсь реализовать 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

Вы печатая информационные каналы, а не данные, которые он содержит. Вам не нужен цикл, вы просто хотите получить затем печать.

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

Теперь я должен указать, что код не собирается блокироваться. Если вы хотите продолжать чтение до тех пор, пока все работы не будут выполнены, вам понадобится какой-то механизм блокировки/координации.

Вы часто будете видеть такие вещи, как

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

Чтобы справиться с этим. Кроме того, просто fyi вы инициализируете свой канал с мощностью по умолчанию (что означает, что это буферный канал), что довольно странно. Я бы рекомендовал рассмотреть некоторые учебные пособия по этой теме, потому что в целом ваш дизайн нуждается в некоторой работе, на самом деле, в улучшении неконкурентных реализаций. Наконец, вы можете найти библиотеки, чтобы отвлечь часть этой работы для вас, и большинство людей, вероятно, порекомендуют вам это сделать. Вот пример; https://github.com/lytics/squaredance

+0

Благодарим вас за ответ, Эван. Я решил использовать буферный канал, потому что мне нужно преобразовать и распечатать несколько структур. Как мне это сделать без буферизованного канала? –

+0

@ScottS. вы можете просто использовать массив для этих целей. Идея канала состоит в том, чтобы обеспечить связь между вашими рабочими потоками и вашим прикладным уровнем, вы можете использовать буферный, это редко делается и немного меняет свою механику. Обычно канал блокируется до тех пор, пока он не читается, поэтому вы должны использовать цикл for, подобный тому, который был у меня выше, который просто продолжает читать канал, пока горутин не говорит, что это сделано, или вы получаете сигнал отключения или прерывания из другого источника. – evanmcdonnal

+0

Если вы собираетесь использовать буферный канал, чтобы просто вставить в него весь массив, вы можете вообще не использовать goroutine, просто используйте блокирующий вызов, потому что вы не будете передавать ваши данные в этот момент, просто подготовьте его асинхронно, ничего не делая, кроме как ждать, пока это будет сделано. – evanmcdonnal