Чтение в одну структуру переписывает другую - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть некоторые проблемы с управлением структурами в Go. У меня есть сложная структура и две переменные, основанные на этой структуре - «предыдущая» и «текущая». Я пытаюсь прочитать данные из tarfile, сделать некоторые расчеты и заменить предыдущие с текущими. Но на следующей итерации чтения, когда я читаю в текущем, мне кажется, что содержимое «предыдущего» перезаписывается и обе переменные становятся одинаковыми. Структура определяется следующим образом:

type Mystruct struct {
    Data       [][]sql.NullString
    Rnames     []string
    Nsize      int
    Msize      int
    Namemaxlen map[string]int
    Valid      bool
    Err        error
}

Переменные не являются указателями. Копирование выполняется как прямое назначение: предыдущий = текущий.

tr := tar.NewReader(f)
var prev, curr Mystruct

for {
    hdr, err := tr.Next()
    if err == io.EOF {
        break
    } else if err != nil {
        log.Panicln(err)
    }

    data := make([]byte, hdr.Size)
    if _, err := io.ReadFull(tr, data); err != nil {
        log.Panicln(err)
    }

    if err = json.Unmarshal(data, &curr); err != nil {
        log.Panicln(err)
    }

    if prev.Valid != true {
        prev = curr
        continue
    }

    // other computations here

    prev = curr
}

Где я не прав? Заранее спасибо.

1 Ответ

0 голосов
/ 07 сентября 2018

Проблема в том, что ваша структура содержит фрагменты, которые в основном являются указателями на память. Копирование этих указателей означает, что ваша копия указывает на ОДНУ ЖЕ память в качестве оригинала, таким образом, они разделяют значения среза. Изменение одного меняет другое.

Вот небольшой пример , чтобы проиллюстрировать проблему:

package main

import "fmt"

type s struct {
    a     int
    slice []int
}

func main() {
    // create the original thing
    prev := s{
        a:     5,
        slice: []int{1, 2, 3},
    }
    // copy the thing into cur
    cur := prev
    // now change cur, changing a will change only cur.a because integers are
    // really copied
    cur.a = 6
    // changing the copied slice will actually change the original as well 
    // because copying a slice basically copies the pointer to memory and the
    // copy points to the same underlying memory area as the original
    cur.slice[0] = 999
    // printing both, we can see that the int a was changed only in the copy but
    // the slice has changed in both variables, because it references the same
    // memory
    fmt.Println(prev)
    fmt.Println(cur)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...