#go
#Вперед
Вопрос:
Я читаю приоритетные очереди в стандартной библиотеке Go здесь, и я смотрю на этот код
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
old[n-1] = nil // avoid memory leak
item.index = -1 // for safety
*pq = old[0 : n-1]
return item
}
Я несколько обеспокоен этим методом извлечения элементов из очереди приоритетов.. Я знаю, что PriorityQueue
тип — это фрагмент указателей в этом примере, и что фрагмент является ссылочным типом, поэтому old := *pq
он только присваивает ссылку на фрагмент и фактически ничего не копирует, но что делает строка *pq = old[0 : n-1]
? Создает ли он другой фрагмент или просто копирует ссылку на старый фрагмент с индексами начала и конца, установленными на 0
и n-1
?
Я хотел бы использовать этот класс для приоритетной очереди с потенциально большим количеством элементов, и я хотел бы избежать ненужных копий.
Комментарии:
1. Рекомендуемое чтение, которое должно ответить на ваш вопрос: go.dev/blog/slices-intro
2. В Go нет ссылок, как и классов. Если вас беспокоит производительность, вы должны измерить.
Ответ №1:
old := *pq
создает копию всего, на что pq
указывает.
Копирование фрагмента создает поверхностную копию — копия поддерживается тем же массивом, что и исходный фрагмент.
*pq = old[0 : n-1]
создает новый фрагмент, который на 1 элемент короче и поддерживается тем же массивом.
Копирование фрагмента обходится дешево, копирование резервного массива обходится дорого.
Обязательное чтение при работе с срезами: срезы перехода: использование и внутренние компоненты