2017-01-20 3 views
1

Я учусь и задал вопрос о некотором примере кода в документации.приемник указателя golang vs value приемник

Я узнал о приемниках указателей и приемниках значений и, насколько я понимаю, если вы хотите изменить сам объект, вам нужно использовать приемник указателя. Я читал больше о интерфейсах в go documentation и нашел этот кусок кода:

type Sequence []int 

// Methods required by sort.Interface. 
func (s Sequence) Len() int { 
    return len(s) 
} 
func (s Sequence) Less(i, j int) bool { 
    return s[i] < s[j] 
} 
func (s Sequence) Swap(i, j int) { 
    s[i], s[j] = s[j], s[i] 
} 

Less и Len метод с использованием значений приемников имеет смысл, потому что они возвращаются данными и не изменяя Sequence состояния. Но в примере Swap мне любопытно, почему он все еще использует приемник значений, когда он выглядит так, будто пытается изменить его состояние. Является ли это ошибкой или мое понимание того, что приемники ценности/указателя некорректны?

Спасибо заранее!

+1

'Sequence' является ссылочным типом, поэтому функция Swap будет менять базовые значения среза. Хорошую статью о срезах можно увидеть здесь: https://blog.golang.org/go-slices-usage-and-internals – squiguy

+1

Вы не изменяете 's'. Вы изменяете 's [i]' и 's [j]'. –

ответ

3

Чтобы разбить бит на комментарий @ squiguy, значение объекта среза само по себе является ссылкой на базовый массив, включая указатель на элемент в массиве, с которого начинается срез, длина среза и емкость среза (количество элементов в базовом массиве от начала среза до конца массива). Когда вы передаете срез функции, эта информация передается по значению, поэтому срез внутри функции по-прежнему относится к одному и тому же базовому массиву. Таким образом, Swap способен обменивать элементы в срезе, даже если сам срез передается по значению.

+0

это имеет большой смысл, я не понял, что срезы всегда были ссылками на массивы. так что, если это особый случай, существуют ли какие-либо другие типы в Go, которые похожи? – phouse512

+2

Карты ведут себя аналогичным образом. Если вы передадите карту функции, и функция внесет изменения в карту, вызывающая сторона увидит это изменение. Каналы также входят в эту группу (типы ссылок), но, вероятно, немного более очевидно, что если вы передаете канал функции, и функция, и вызывающая сторона имеют ссылку на тот же канал. –

Смежные вопросы