Определение объема переменных в цикле for - PullRequest
0 голосов
/ 29 января 2020

Следующая программа манипулирует двумя массивами. Алгоритм не имеет большого значения, кроме как отметить, что массив tmp постепенно становится меньше.

package main

import (
    "strings"
    "fmt"
)

func arrayToString(a []int, delim string) string {
    return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim, -1), "[]")
}

func numSeries(arr []int) ([]int, []int) {
    return arr[:2], arr[2:]
}

func main() {
    highnum := []int{8,7}
    tmp := []int{6,5,4,3,2,1}
    curr := []int{}
//    fRight := ""
    for i, v := range highnum {
        curr, tmp = numSeries(tmp)
        fmt.Printf("v %d numSeries result curr %s tmp %s\n", v, arrayToString(curr, ", " ), arrayToString(tmp, ", " ) )
        fmt.Printf("final (1) %s\n", arrayToString(tmp, ", " ) )       
//        fRight += "[" + arrayToString(append(curr, v), ", ") + "]"
        if i == len(highnum)-1 {
            fmt.Printf("final (2) %s\n", arrayToString(tmp, ", " ) )
        }
//        fmt.Printf("fRight |%s|\n", fRight)        

    }
}

Результаты:

v 8 numSeries result curr 6, 5 tmp 4, 3, 2, 1
final (1) 4, 3, 2, 1
v 7 numSeries result curr 4, 3 tmp 2, 1
final (1) 2, 1
final (2) 2, 1

Программа работает - final (1) и final ( 2) комментарии в выводе имеют одинаковое значение. Однако, если я раскомментирую три закомментированных утверждения выше, я получу неверный результат Вот неправильная программа и результат.

package main

import (
    "strings"
    "fmt"
)

func arrayToString(a []int, delim string) string {
    return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim, -1), "[]")
}

func numSeries(arr []int) ([]int, []int) {
    return arr[:2], arr[2:]
}

func main() {
    highnum := []int{8,7}
    tmp := []int{6,5,4,3,2,1}
    curr := []int{}
    fRight := ""
    for i, v := range highnum {
        curr, tmp = numSeries(tmp)
        fmt.Printf("v %d numSeries result curr %s tmp %s\n", v, arrayToString(curr, ", " ), arrayToString(tmp, ", " ) )
        fmt.Printf("final (1) %s\n", arrayToString(tmp, ", " ) )       
        fRight += "[" + arrayToString(append(curr, v), ", ") + "]"
        if i == len(highnum)-1 {
            fmt.Printf("final (2) %s\n", arrayToString(tmp, ", " ) )
        }
        fmt.Printf("fRight |%s|\n", fRight)        

    }
}

Результат:

v 8 numSeries result curr 6, 5 tmp 4, 3, 2, 1
final (1) 4, 3, 2, 1
fRight |[6, 5, 8]|
v 7 numSeries result curr 8, 3 tmp 2, 1
final (1) 2, 1
final (2) 7, 1
fRight |[6, 5, 8][8, 3, 7]|

Обратите внимание, что заключительные (1) и заключительные (2) комментарии имеют разные значения. Это не верно. Я подозреваю, что этот тип поведения является полностью правильным, и я влюбляюсь в «гочу» новичка. Я был бы признателен, если бы кто-то мог указать на существующий вопрос StackOverflow, который дает решение или описывает, что происходит. Я был бы особенно рад увидеть ссылку на официальное определение языка, посвященное этой проблеме.

1 Ответ

1 голос
/ 29 января 2020

Это здесь:

fRight += "[" + arrayToString(append(curr, v), ", ") + "]"

В частности, append. Ключевым моментом здесь является то, что срезы - это представления массивов. curr и tmp указывают на один и тот же базовый массив, curr является его начальной частью, а tmp - концом. Способ работы append заключается в том, что если срез имеет достаточную емкость, он просто добавит элемент в конец среза и увеличит len. Когда вы запускаете этот append, curr имеет достаточную емкость, поэтому v добавляется в конец curr, что является первым элементом tmp. Таким образом, вы перезаписываете этот элемент.

...