Go 将heap.Interface作为结构
我正在使用Go的包创建一个优先级队列。文件中有一个 我正在创建的队列需要基于结构而不是切片,因为它需要其他属性,如互斥体Go 将heap.Interface作为结构,go,Go,我正在使用Go的包创建一个优先级队列。文件中有一个 我正在创建的队列需要基于结构而不是切片,因为它需要其他属性,如互斥体 type PQueue struct { queue []*Item sync.Mutex } 我实现了所有需要的方法 问题是我的PQueue.Push方法似乎没有永久性地向PQueue.queue添加值 func (p PQueue) Push(x interface{}) { p.Lock() defer p.Unlock() i
type PQueue struct {
queue []*Item
sync.Mutex
}
我实现了所有需要的方法
问题是我的PQueue.Push
方法似乎没有永久性地向PQueue.queue
添加值
func (p PQueue) Push(x interface{}) {
p.Lock()
defer p.Unlock()
item := x.(*Item)
item.place = len(p.queue) // the index of an item in the queue
p.queue = append(p.queue, item)
// len(p.queue) does increase
// after the functions exits, the queues length has not increased
}
如果我在此函数末尾打印p.queue
的长度,则长度增加。然而,在函数退出之后,原始结构似乎没有得到更新
我认为这可能是因为func(p PQueue)
不是指针。为什么会这样?有办法解决吗?如果我使用func(p*PQeueue)Push(x interface{})
来代替,我需要实现自己的堆,因为heap.interface
特别不需要指针。这是我唯一的选择吗
我认为这可能是因为func(pPQUE)不是指针
对。引述:
对值调用[the method]将导致该方法接收
值的副本,因此将放弃任何修改
你说:
接口特别不需要指针
我很困惑,您所指的示例实际上是使用指针:
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
也许发生了什么事
我认为这可能是因为func(pPQUE)不是指针
对。引述:
对值调用[the method]将导致该方法接收
值的副本,因此将放弃任何修改
你说:
接口特别不需要指针
我很困惑,您所指的示例实际上是使用指针:
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
可能发生了其他事情?关于与
Push
方法的接收器相关的问题,您是对的:该方法将接收PQueue
的副本,因此对结构所做的任何更改都不会持续
将方法更改为使用指针作为接收器是正确的更改,但这也意味着PQueue
不再实现heap.Interface
。这是因为Go不允许使用指针指向存储在接口变量中的值,因此不会自动将q.Push()
转换为(&q).Push()
但这并不是死胡同,因为
*PQueue
仍然应该实现堆接口。因此,如果您以前调用的是heap.Init(q)
,只需将其更改为heap.Init(&q)
,您的问题与Push
方法的接收者相关,这是正确的:该方法将接收PQueue
的副本,因此对结构所做的任何更改都不会持久
将方法更改为使用指针作为接收器是正确的更改,但这也意味着PQueue
不再实现heap.Interface
。这是因为Go不允许使用指针指向存储在接口变量中的值,因此不会自动将q.Push()
转换为(&q).Push()
但这并不是死胡同,因为*PQueue
仍然应该实现堆接口。因此,如果您以前调用的是heap.Init(q)
,只需将其更改为heap.Init(&q)
,问题是您正在附加到切片的副本。因此,更改将显示在函数中,但一旦从函数返回,更改将丢失
在将切片传递给函数的部分中:
理解这一点很重要,即使切片包含
指针,它本身就是一个值。在封面下,它是一个结构值
拿着一个指针和一个长度。它不是指向结构的指针
使用append可以修改切片标头。及
因此,如果我们想编写一个修改头的函数,我们必须
将其作为结果参数返回
或:
让函数修改切片头的另一种方法是传递
指向它的指针
因此,如果要使用append修改指针,则需要传递指针。只需将方法更改为使用指针接收器。要实现这一点,您需要使用类似于heap.init(&pq)
的指针调用init,如您链接到的示例所示,该示例正是这样做的,并且还使用指针接收器
从方法集上的:
对应指针类型*T的方法集是所有方法的集合
用receiver*T或T声明(也就是说,它还包含方法
一组T)
因此,使用指针类型将与值和指针接收器一起工作,并且仍然实现接口。问题在于,您正在附加到切片的副本。因此,更改将显示在函数中,但一旦从函数返回,更改将丢失
在将切片传递给函数的部分中:
理解这一点很重要,即使切片包含
指针,它本身就是一个值。在封面下,它是一个结构值
拿着一个指针和一个长度。它不是指向结构的指针
使用append可以修改切片标头。及
因此,如果我们想编写一个修改头的函数,我们必须
将其作为结果参数返回
或:
让函数修改切片头的另一种方法是传递
指向它的指针
因此,如果要使用append修改指针,则需要传递指针。只需将方法更改为使用指针接收器。为了实现这一点,您需要使用类似于heap.init(&pq)
的指针调用init,如您链接到的示例所示,该示例正是这样做的,并且还使用指针接收器