Добавление к фрагменту с достаточной емкостью с использованием приемника значения - PullRequest
0 голосов
/ 26 октября 2018

Может ли кто-нибудь помочь мне понять, что здесь происходит?

package main

import (
    "fmt"
)

func appendString(slice []string, newString string) {
    slice = append(slice, newString)
}

func main() {
    slice := make([]string, 0, 1)
    appendString(slice, "a")
    fmt.Println(slice)
}

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

Что не так с моими предположениями

1 Ответ

0 голосов
/ 26 октября 2018

Давайте добавим окончательный оператор печати, чтобы увидеть результат:

slice := make([]string, 0, 1)
fmt.Println(cap(slice))
appendString(slice, "a")
fmt.Println(slice)

И вывод будет (попробуйте на Go Playground ):

1
[]

Что правильно. Можно ожидать, что результат будет:

1
[a]

Причина, по которой это не так, заключается в том, что, хотя новый резервный массив не будет выделен, заголовок слайса в переменной slice внутри main() равен , а не изменен , он все равно будет удерживайте length = 0. Изменяется только заголовок слайса, сохраненный в локальной переменной slice внутри appendString() (параметр), но эта переменная не зависит от значения slice.

в main.

Если вы измените значение main slice, вы увидите, что массив поддержки содержит новую строку:

slice := make([]string, 0, 1)
fmt.Println(cap(slice))
appendString(slice, "a")
fmt.Println(slice)

slice = slice[:1]
fmt.Println(slice)

Теперь вывод будет (попробуйте на Go Playground ):

1
[]
[a]

Именно поэтому встроенный append() должен возвращать новый срез: потому что даже если новый вспомогательный массив не требуется, заголовок среза (который содержит длину) придется изменить (увеличить ) если добавлено более 0 элементов.

Вот почему appendString() также должен вернуть новый срез:

func appendString(slice []string, newString string) []string {
    slice = append(slice, newString)
    return slice
}

или коротко:

func appendString(slice []string, newString string) []string {
    return append(slice, newString)
}

Что вы должны переназначить, где вы используете:

slice := make([]string, 0, 1)
fmt.Println(cap(slice))
slice = appendString(slice, "a")
fmt.Println(slice)

И тогда вы сразу же получите ожидаемый результат (попробуйте на Go Playground ):

1
[a]
...