перейти на срез диапазона и вызов метода goroutine, логика позади

Код выглядит следующим образом:

package main

    import (
        "fmt"
        "time"
    )

    type field struct {
        name string
    }

    func (p *field) print() {
        fmt.Println(p.name)
    }

    func main() {
        data := []field{{"one"},{"two"},{"three"}}
        for _,v := range data {
            go v.print()
        }
        time.Sleep(3 * time.Second)
    }

Я знаю, что код неверен, потому что переменная цикла for повторно используется в цикле for-range.

Когда горутине удалось запуститься, значение v may было изменено. поэтому результат печати будет "three,three,three".

Но когда мы изменяем переменную данных в другое объявление как:

data := []*field{{"one"},{"two"},{"three"}}

результат печати будет "one ,two,three".

Я не понял, почему. Имеет ли значение указатель или какой-либо другой механизм?

Я прочитал это из этой статьи. Но плакат не сказал, почему. Или это просто случай, выход правильный.


person cilendeng    schedule 01.06.2015    source источник
comment
Я не вижу, как data определяется по-другому во второй раз.   -  person    schedule 01.06.2015
comment
@LutzHorn извините за опечатку и вашу правильность. в первом неправильном случае данные определяются как данные := []поле{{один},{два},{три}} .а новые данные := []*поле{{один},{два},{ три}}   -  person cilendeng    schedule 01.06.2015
comment
Пожалуйста, отредактируйте свой вопрос и исправьте код.   -  person    schedule 01.06.2015


Ответы (1)


В первом цикле v — это значение элемента field. Поскольку v является адресуемым, на него автоматически ссылаются как на приемник указателя для метода print(). Итак, v.print() использует адрес самого v, и содержимое этого адреса перезаписывается при каждой итерации цикла.

Когда вы изменяете объявление для использования *field, v теперь является указателем на значение field. Когда вы вызываете v.print() в этом случае, вы работаете со значением, на которое указывает v, которое хранится в data, и перезапись v не имеет никакого эффекта.

person JimB    schedule 01.06.2015
comment
правильно, операция выполняется над элементом, хранящимся в data, но на элемент, над которым выполняется операция, ссылается v, когда цикл запускается, v перезаписывается. когда горутина наконец вызывается, v указывает на последний элемент. Как v может сохранить ссылку на несколько любых значений указателя или структуры или что-то еще. - person cilendeng; 02.06.2015
comment
или, может быть, я пропустил какой-то механизм. Получил ли golang реальный адрес, на который указывает v .или v извлекается до тех пор, пока горутина, наконец, не получит возможность запуститься? значение v предварительно выбирается или извлекается во время выполнения - person cilendeng; 02.06.2015
comment
@cilendeng: я не понимаю вашего вопроса. Никакого волшебства не происходит, в Go все является значением, а копирование происходит в момент присваивания. - person JimB; 03.06.2015
comment
Я получил это. Параметры новой горутины оцениваются и передаются текущей горутине (много раз текущая является основной горутиной). но через некоторое время она назначается новой горутине. - person cilendeng; 04.06.2015