Ошибка cannot use type []byte as type *[]byte in argument to sliceArr()
происходит из-за того, что вы еще не отправили (вы пытались передать срез, а не указатель на фрагмент до sliceArr()
).
Как другая ошибка (cannot slice type *[]byte
), вам просто нужно использовать скобки для группировки указатель разыменования:
*buf = (*buf)[i:]
А вы случайно не учел =
знак от объявления переменной. Кроме этого, все работает, как вы написали:
func main() {
var buf = []byte{1, 2, 3, 4, 5}
sliceArr(&buf, 2)
fmt.Println(buf)
}
func sliceArr(buf *[]byte, i int) {
*buf = (*buf)[i:]
}
Output (попробовать его на Go Playground):
[3 4 5]
Примечание:
Обратите внимание, что specification states, что если p
является указатель на массив , p[low:high]
является сокращением для (*p)[low:high]
, то есть указателем являются разыменованные автоматы для вас. Это не происходит автоматически, если p
является указателем на фрагмент, p[low:high]
недействителен, так как вы не можете нарезать указатель. Таким образом, вы должны разыменовать указатель вручную в случае указателей на срезы.
Причина этого отклонения заключается в том, что указатель на срез очень редок, поскольку срезы уже являются «справедливыми» дескрипторами (к смежной части базового массива), а срезы передаются без указателя большую часть времени, поэтому если в редком случае (например, этот) вам нужно передать указатель, вам нужно четко указать его обработку. Массивы, с другой стороны, представляют все элементы; присваивание или передача массивов копирует все значения, поэтому гораздо чаще используется указатель на массивы (чем указатели на срезы) - поэтому вполне оправданно иметь больше поддержки языка для работы с указателями массива.
Также обратите внимание, что ваша задача может быть достигнута за счет использования только фрагмента (не указателя) в качестве типа параметра и возврата нового значения среза, который, конечно, должен быть назначен у вызывающего (хорошим примером для этого является встроенный append()
функция).
Примечание # 2:
Если тип параметра является срез (а не указатель на срезе), и вы передаете кусочек, основной массив не копируется, только заголовок секции.Но в этом случае, если вы разрезаете аргумент (который является копией заголовка среза) и вы назначаете новый срез (заголовок среза) на аргумент, вы просто изменяете значение параметра (локальную переменную) и а не исходное значение (переменная), которое было передано, поэтому он не будет работать.
Прочитайте следующие сообщения пользователя для более подробной информации по кусочкам:
Go Slices: usage and internals
Arrays, slices (and strings): The mechanics of 'append'