Почему я не могу изменить значения в диапазоне структур типов? - PullRequest
0 голосов
/ 29 июня 2018

Это мой первый пост, поэтому, пожалуйста, будьте осторожны со мной. :) ... Я довольно знаком со многими традиционными языками программирования, но я новичок в Go и не могу понять, как использовать слайсы и диапазоны. Код программы и комментарии ниже иллюстрируют мой ужас. Спасибо!

package main

import (
    "fmt"
    "time"
)

type myStruct struct {
    Name  string
    Count int
}

Написал свою собственную функцию Mod, потому что я не смог найти в библиотеках Go.

func modMe(mod int, value int) int {
    var m int
    var ret int

    m = value / mod
    ret = value - m*mod
    return ret
}

func main() {
    mod := 4
    cnt := 16
    fmt.Printf("Record mod is %d\r\n", mod)

Объявление массива структуры и добавление некоторых записей

    chartRecords := []myStruct{}

    for i := 0; i<=cnt ;i++ {
        n := myStruct{Count: i, Name: fmt.Sprintf("Joe%2d", i)}                         //Load some data
        chartRecords = append(chartRecords,n)
    }

Загрузка данных дает ожидаемый результат

    fmt.Printf("======ORIGINAL LOADED VALUES========\r\n")                                  
    i := 0
    for _, elem := range chartRecords {
        fmt.Printf("No: %2d | Count: %2d | Name = %s\r\n", i, elem.Count, elem.Name)    //Print out original values in the range
        i = i + 1
    }

Теперь я изменяю значения и печатаю их, чтобы увидеть, что они выглядят измененными. Это выглядит как ожидалось.

    fmt.Printf("======MODIFIED VALUES EXPECTED========\r\n")                                    
    i = 0
    for _, elem := range chartRecords {                                                 //looping thru the range of the data records
        mm := modMe(mod, i)                                                             //modMe is my function to return the Mod of a number based on moduls 'mod'
        elem.Count = mm                                                                 //assigning the new mod value to Count
        fmt.Printf("No: %2d | Count: %2d | Name = %s\r\n", i, elem.Count, elem.Name)    //Print out this elem.Count element in the range
        i = i + 1                                                                       
    }

Теперь я просто повторяю тот же диапазон снова и распечатываю ту же самую вещь. Но вывод показывает исходные значения. Я не понимаю, почему это происходит. Я предполагаю, что это связано с кусочками и добавлением значений, а не заменой значений.

    fmt.Printf("======CHECK AGAIN AND VALUES ARE BACK TO ORIGINAL========\r\n")                                         //Now lets loop through the same range
    i = 0
    for _, elem := range chartRecords {
        fmt.Printf("No: %2d | Count: %2d | Name = %s\r\n", i, elem.Count, elem.Name)    //Print out this elem.Count element in the range
        i = i + 1
    }                                                                                   //But this output shows the original values  WHY??
    time.Sleep(60 * time.Second)
}

Вывод выглядит так ... Вывод скриншота

Заранее спасибо за совет.

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Добавление этих строк из небольшой помощи моего друга Русса.

Цитата: Привет, Виктор, если я правильно помню это, когда вы… просматриваете коллекцию, возвращаемый объект является копией оригинала, хранящегося в коллекции («семантика значения»). Итак, переменная elem - это копия, которой вы назначаете счетчик. Это правильный код, но вы не обновляете коллекцию так, как ожидаете. Подумайте о том, чтобы настроить цикл for… range на это:

    fmt.Printf("======NOW MODIFY VALUES THIS WAY========\r\n")                                  
    i = 0
    for idx := range chartRecords { 
        mm := modMe(mod, i)  
        chartRecords[idx].Count = mm  
        fmt.Printf("No: %2d | Count: %2d | Name = %s\r\n", i, chartRecords[idx].Count, chartRecords[idx].Name)  //Print out this elem.Count element in the range
        i = i + 1    
    } 

    fmt.Printf("======CHECK AGAIN AND VALUES ARE AS DESIRED========\r\n")                                       //Now lets loop through the same range
    i = 0
    for _, elem := range chartRecords {
        fmt.Printf("No: %2d | Count: %2d | Name = %s\r\n", i, elem.Count, elem.Name)    //Print out this elem.Count element in the range
        i = i + 1
    } 

Теперь я понимаю лучше и надеюсь, что это поможет другим новичкам, таким как я ...

Хорошего дня!

Victor

0 голосов
/ 29 июня 2018

Спецификация языка программирования Go

Для операторов с предложением диапазона

Оператор "for" с предложением "range" повторяет все записи массива, среза, строки или карты или значений, полученных на канале. Для каждой записи он присваивает значения итерации соответствующей итерации переменные, если они присутствуют, а затем выполняет блок.


Спецификация языка программирования Go легко читается.

Поместите обновленную переменную elem обратно в срез chartRecords:

for i, elem := range chartRecords {
    elem.Count = modMe(mod, i)
    chartRecords[i] = elem
    fmt.Printf("No: %2d | Count: %2d | Name = %s\r\n", i, elem.Count, elem.Name)
}
...