2015-06-01 2 views
1

кода является следующий вид:идут для диапазона среза и метод 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) 
    } 

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

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

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

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

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

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

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

+1

Я не вижу, как «данные» определяются разными во второй раз. –

+0

@ LutzHorn извините за опечатку и вашу неверность. первый неверный случай, данные определяются как «data: = [] field {{« one »}, {« two »}, {" three "}}", а новое одно: data: = [] * field { {"one"}, {"two"}, {"three"}} " – cilendeng

+0

Пожалуйста, отредактируйте ваш вопрос и исправьте код. –

ответ

1

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

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

+0

Правильно, операция находится на элементе, хранящемся в 'data', но элемент, который работает, ссылается на' v', когда цикл запущен, 'v' перезаписывается. Когда gotoutine наконец-то вызывается , v указал на последний элемент. Как 'v' сохранить ссылку на несколько значений указателя или структуры или что-то еще. – cilendeng

+0

или, может быть, я пропустил какой-то механизм. Получил ли golang реальный адрес, на который 'v' указывает на. Или' v', до тех пор, пока goroutine не получит шанс запустить? значение 'v' предварительно задано или выполняется время ожидания – cilendeng

+0

@cilendeng: я не понимаю ваш вопрос. Волшебства не происходит, в Go все значение, и копия происходит во время задания. – JimB