Почему срез может быть изменен в функциях путем назначения, но не для a для l oop? - PullRequest
0 голосов
/ 22 февраля 2020

Мне нужно, чтобы каждая оценка была изменена на некоторые другие значения здесь, в функции, которая получает указатель среза, я могу изменить значения, назначив, но ничего не изменилось, если я сделаю это в для l oop. Почему это так?

package main

import (
    "fmt"
    "sync"
    "time"
)

type TestType struct {
    id    int
    score float64
}

func worker(index int, wg *sync.WaitGroup, listScores *[][]TestType) {
    defer wg.Done()
    time.Sleep(1000 * time.Millisecond)

    // It works by assigning.
    (*listScores)[index] = []TestType{{index + 1, 2.22},
        {index + 1, 2.22},
        {index + 1, 2.22},}
    // It doesn't work in a for loop.
    //for _, score := range (*listScores)[index] {
    //  score.score = 2.22
    //}
}

func main() {
    scoresList := [][]TestType{
        {{1, 0.0},
            {1, 0.0},
            {1, 0.0},},
        {{2, 0.0},
            {2, 0.0},
            {2, 0.0},
        },}

    fmt.Println(scoresList)

    var wg sync.WaitGroup
    for i, _ := range scoresList {
        wg.Add(1)
        go worker(i, &wg, &scoresList)
    }
    wg.Wait()

    fmt.Println(scoresList)
}

Баллы можно изменить на 2,22, присвоив ему новый целый срез:

[[{1 0} {1 0} {1 0}] [{2 0} {2 0} {2 0}]]
[[{1 2.22} {1 2.22} {1 2.22}] [{2 2.22} {2 2.22} {2 2.22}]]

Но если я сделаю это в для l oop как в комментарии вывод выглядит так:

[[{1 0} {1 0} {1 0}] [{2 0} {2 0} {2 0}]]
[[{1 0} {1 0} {1 0}] [{2 0} {2 0} {2 0}]]

1 Ответ

1 голос
/ 22 февраля 2020

Поскольку range дает вам два элемента:

  • индекс
  • a копия элемента, если вы выполняете итерацию среза.

Код может быть изменен на следующий без использования потока:

package main

import (
    "fmt"
)

type testType struct {
    id    int
    score float64
}

func main() {
    scoresList := [][]testType{
        {{1, 0.0}, {1, 0.0}, {1, 0.0}},
        {{2, 0.0}, {2, 0.0}, {2, 0.0}}}
    fmt.Println(scoresList)
    for i := range scoresList {
        scoresList[i] = []testType{{i + 1, 2.22},
            {i + 1, 2.22},
            {i + 1, 2.22}}
    }
    fmt.Println(scoresList)
}

Если вы хотите использовать поток, чем вы можете использовать следующий:

package main

import (
    "fmt"
    "sync"
    "time"
)

type TestType struct {
    id    int
    score float64
}

func worker(index int, wg *sync.WaitGroup, listScores *[][]TestType) {
    defer wg.Done()
    time.Sleep(1000 * time.Millisecond)

    for i := range (*listScores)[index] {
        (*listScores)[index][i].score = 2.22
    }
}

func main() {
    scoresList := [][]TestType{
        {{1, 0.0},
            {1, 0.0},
            {1, 0.0}},
        {{2, 0.0},
            {2, 0.0},
            {2, 0.0},
        }}

    fmt.Println(scoresList)

    var wg sync.WaitGroup
    for i, _ := range scoresList {
        wg.Add(1)
        go worker(i, &wg, &scoresList)
    }
    wg.Wait()

    fmt.Println(scoresList)
}
...