обновление одной позиции в срезе срезов приводит к нескольким обновлениям

# #go #pointers #slice

Вопрос:

Я учусь ходить и играть с кусочками, но у меня проблема

У меня есть матрица по умолчанию с «.», но когда я пытаюсь изменить позицию 0,0 на символ»#», все позиции n, 0 имеют»#», другими словами, я начинаю с этого:

 [. . . . .]
[. . . . .]
[. . . . .]
[. . . . .]
[. . . . .]
 

Измените положение 0,0 с помощью этой функции:

 func drawSym(table *[][]string) {
    (*table)[0][0] = "#" 
}
 

И я получаю

 [# . . . .]
[# . . . .]
[# . . . .]
[# . . . .]
[# . . . .]
 

Когда мне нужна такая матрица, как эта

 [# . . . .]
[. . . . .]
[. . . . .]
[. . . . .]
[. . . . .]
 

Полный код программы находится на игровой площадке https://play.golang.org/p/xvkRhmNvdIP

Комментарии:

1. В вашей таблице 5 строк, но ваш код создает только одну строку и повторно использует ее для всех строк. У вас есть только одна строка, используемая в нескольких местах. Если вы измените его, вы увидите изменения везде, где вы на него ссылаетесь.

Ответ №1:

Если размер матрицы не меняется, нет необходимости передавать указатель на ваш срез (или срез срезов).

Таким образом, вы можете упростить создание/инициализацию своей таблицы следующим образом:

 func createTable(size int) (table [][]string) {
    table = make([][]string, size)

    for i := 0; i < size; i   {
        table[i] = make([]string, size) // create a new row per iteration
        for j := 0; j < size; j   {
            table[i][j] = "."
        }
    }
    return
}

table := createTable(5)
 

функции draw и print также упрощены, так как им также не нужен указатель среза:

https://play.golang.org/p/KmwynzUj0I-

Ответ №2:

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

 package main

import (
    "fmt"
)

func main() {
    table := make([][]string, 5)
    initTable(table)
    printTable(table)
    drawSym(table)
    printTable(table)

}

func drawSym(table [][]string) {
    (table)[0][0] = "#"

    (table)[1][1] = "%"
}

func initTable(table [][]string) {

    for i := 0; i < len(table); i   {
        table[i] = make([]string, len(table))
        for j := 0; j < len(table); j   {
            table[i][j] = "."
        }
    }
}

func printTable(table [][]string) {
    for i := 0; i < len(table); i   {

        fmt.Println((table)[i])
    }
}
 

Выход:

 [. . . . .]
[. . . . .]
[. . . . .]
[. . . . .]
[. . . . .]
[# . . . .]
[. % . . .]
[. . . . .]
[. . . . .]
[. . . . .]
 

Ответ №3:

Если ваша матрица имеет фиксированный размер, вы можете использовать массивы вместо срезов ( [5][5]string ). Чтобы предотвратить дублирование кода и упростить обслуживание, вы можете создать тип желаемой длины для этой матрицы ( type myMatrix [5][5]string ) и использовать этот тип в своем коде ( func printTable(table myMatrix) ).

Такие как

 package main

import (
    "fmt"
)

type myMatrix [5][5]string

func main() {
    var table myMatrix

    for i := 0; i < len(table); i   {
        for j := 0; j < len(table); j   {
            table[i][j] = "."
        }
    }

    table[0][0] = "#"

    printTable(table)

}

func printTable(table myMatrix) {
    for i := 0; i < len(table); i   {
        fmt.Println(table[i])
    }
}
 

https://play.golang.org/p/Ok0DBGSfJlA