作者回复: 比如你用 list.New 函数创建了一个 List 类型的双向链表,然后通过它的一些方法往里面塞了一些元素。可以往里面塞的元素的方法有 PushFront、PushBack、InsertAfter、InsertBefore 等。
但是你发现没有,这些方法接受的新元素的类型都是 interface{} 的。也就是说,这个 List 类型的链表只接受 interface{} 类型的新元素值。
而当新元素值进入链表之后,链表会把它们再包装成 list.Element 类型的值。你看,那些往里塞元素值的方法返回的都是被包装后的 *list.Element 类型的元素值。
当你像我这样浏览了 container/list.List 类型的相关 API 之后,就应该可以明白我问这个问题的背景了。
这个 List 类型只会接受 interface{} 类型的新元素值,并且只会吐出 *list.Element 类型的已有元素值。显然,任何移动已有元素值或者删除已有元素值的方法,都只会接受该链表自己吐出来的“Element 值”。因此,对于我们自己生成的“Element 值”,这个链表的任何方法都是不会接受的。
当然了,如果你之前完全没用过 List 类型,可能会觉得这个问题有些突兀。但是当你看完下面的详细解释之后,我相信你就会有所了解了。
我们这个专栏的一个风格就是:“先抛出问题,然后再解释前因后果”。目的就是,逼迫大家在碰到问题之后自己先去了解背景并试着找找答案,然后再回来看我的答案。这样的话,你对这些知识点的记忆会更牢固,不容易忘。
我非常希望这个专栏能成为大家的“枕边书”,而不是听听音频就放在一边的那种。所以才有了这样的结构设计。如果你们能在今后碰到问题时想起这个专栏,到这里翻一翻并能找到答案的线索,那我就太高兴了。
作者回复: 这需要一个过程,之前list也不是标准库中的一员。况且也没必要把太多的东西多做到语言里,这样反倒不利于后面的扩展。
作者回复: 嗯,也算是与时俱进吧,未来有脑机接口了,也就用不着这些了。
作者回复: ✅
作者回复: 按照你这三行代码,应该是 789 -> 456 -> 123 啊,你那个“789-》456-》ni”是怎么出来的?
这个链表里所谓的 root 就是用来表示链表两端的尽头的。所以,这个链表的末端实际上并不是 nil ,而是 root。只是在 Element 的 Next 方法中,如果发现它的 next 字段的值等于 root,就会返回 nil 而已。
明白了吗?
作者回复: 当然不一样,list.New 返回的是指针值。另外你可以再看看讲结构体和方法那篇文章。
作者回复: 建议大家在阅读这一篇文章时对照着 container 包的文档看。对这几个类型的 API 有一定了解之后,使用就是水到渠成的事情了。
自己先试一试,如果有具体的问题,可以来这里问。
作者回复: 我这些是对照list源码说的,你可以去看一看list的源码,这些问题就都迎刃而解了。