Pointers 使用指针索引-指针如何使用切片?
在下面的Pointers 使用指针索引-指针如何使用切片?,pointers,go,slice,Pointers,Go,Slice,在下面的main()code中: package main import ( "fmt" "github.com/myhub/cs61a/poetry" ) func main() { p := poetry.NewPoem([][]string{ { "And from my pillow, looking forth by light", "Of moon or favoring stars, I
main()
code中:
package main
import (
"fmt"
"github.com/myhub/cs61a/poetry"
)
func main() {
p := poetry.NewPoem([][]string{
{
"And from my pillow, looking forth by light",
"Of moon or favoring stars, I could behold",
"The antechapel where the statue stood",
"Of Newton, with his prism and silent face,",
"The marble index of a mind forever",
"Voyaging through strange seas of thought, alone.",
},
{
"inducted into Greek and Christian",
"modes of thinking, must take a longer way around.",
"Like children born into love, they exult in the here",
"who have felt separation and grave misgivings, they",
"and of humanity, and of God. Great literature, like",
"struggles to reconcile suffering with faith in the ",
},
})
fmt.Printf("%T\n", p[0])
}
p[0]
使用下面的函数构造函数指向第一节就可以了:
package poetry
type Line string
type Stanza []Line
type Poem []Stanza
func NewPoem(s [][]string) Poem {
var poem Poem
for _, stanza := range s {
var newStanza Stanza
for _, line := range stanza {
newStanza = append(newStanza, Line(line))
}
poem = append(poem, newStanza)
}
return poem
}
如果,
NewPoem()
返回类型为*Poem
的值,如下所示:
package poetry
type Line string
type Stanza []Line
type Poem []Stanza
func NewPoem(s [][]string) *Poem {
var poem Poem
for _, stanza := range s {
var newStanza Stanza
for _, line := range stanza {
newStanza = append(newStanza, Line(line))
}
poem = append(poem, newStanza)
}
return &poem
}
然后,main()
中的p[0]
给出以下错误:
Invalid operation: p[0] (type *poetry.Poem does not support indexing)
为什么指向字符串片段片段的指针不支持
p[0]
语法
为什么指向字符串片段片段的指针不支持p[0]
语法
简短回答:因为语言规范不允许这样做
较长的回答:因为很少使用指向切片的指针,为什么要用一些对许多人没有好处的东西使语言复杂化?如果在极少数情况下确实需要它,只需取消对指针的引用并为切片编制索引
请注意,规范允许对数组指针进行索引或切片,因为在使用数组时,指向数组的指针比指向切片的指针更经常、更有用。请在此处阅读更多信息:
为什么指向字符串切片的切片的指针不支持p[0]语法
因为指向(任何内容)切片的指针不是语言定义的支持索引的类型。以下是规格:
A[x]
形式的主表达式表示数组的元素、指向数组的指针、切片、字符串或由x索引的映射。值x分别称为索引键或映射键。以下规则适用:
资料来源:
它接着明确定义了索引如何为每个受支持的类型工作,最后指出,否则a[x]是非法的
因此,基本上您试图做一些语言不允许的事情
至于原因,再谈谈您的设计,指向切片的指针很少有意义 首先,当您传递一个片时,移动的数据量是绝对最小的(它只是一个片头,通常是十几个字节),因此与传递指针相比没有明显的增益 然后,在你对问题的评论中,你说,“提供一个指向诗歌类型的指针看起来是一个更好的抽象。”这实际上取决于你想对诗歌类型做什么。考虑到您提供的一些细节,我认为传递
*Poem
实际上是一个更糟糕的设计选择,而不仅仅是Poem
,因为指针没有任何好处,而且实际上会使事情复杂化。例如,您不能使用索引(p[0]
)
在对这个回答的评论中,您问:您是否看到
[]字符串{…}
传递给NewPoem()
是一个好方法
就像我在评论中提到的,我们没有很多细节,所以很难说。但目前,您可以这样做来创建一首诗
:
p := poetry.Poem{
{
"And from my pillow, looking forth by light",
"Of moon or favoring stars, I could behold",
"The antechapel where the statue stood",
"Of Newton, with his prism and silent face,",
"The marble index of a mind forever",
"Voyaging through strange seas of thought, alone.",
},
{
"inducted into Greek and Christian",
"modes of thinking, must take a longer way around.",
"Like children born into love, they exult in the here",
"who have felt separation and grave misgivings, they",
"and of humanity, and of God. Great literature, like",
"struggles to reconcile suffering with faith in the ",
},
}
fmt.Printf("%T\n", p[0])
不需要循环或追加或NewPoem
函数或任何直接从字符串创建诗歌的东西。直接使用类型Poem{…}
如果您需要执行一些不同的操作,例如通过读取(比如)文件中的数据来创建诗歌,您可以创建如下函数:
package poetry
func ReadFrom(rd io.Reader) Poem { ... }
但是对于直接在代码中创建一首诗来说,没有必要把事情复杂化
为什么指向字符串切片的切片的指针不支持p[0]语法
因为它是一个指针,所以里面没有像数组或切片这样的可索引元素。
如果希望索引访问节
,可以取消引用指针(从而获得一个切片),然后访问切片中的第0
”元素:
fmt.Printf(“%T\n”,(*p)[0])
输出:
main.Stanza
或示例的完整代码:
但是。
您真的需要指向切片的指针吗?Golang中的切片是非常轻量级的结构-由3个64位值组成:指向包含数据的数组的指针、数组的当前长度和数组的最大长度-所谓的切片容量
我们可以将传递切片与向切片传递指针进行比较:
f, _ := os.Open("/tmp/dat")
// Create a buffer of size 5
b1 := make([]byte, 5)
// Read some bytes from the beginning of the file.
// Allow up to 5 to be read - this value is taken from slice length
// Read returns how many bytes actually were read.
n, _ := f.Read(b1)
更多信息:@CeriseLimón很抱歉。。。。queryedited对于它的价值,当您传递切片时复制的内容是一个非常小的结构,引用内容(指针、长度和容量)。内容没有被复制。如果你是为了提高效率而传递一个指针,你可能不需要这样做。关于指针什么时候有帮助的整个问题会出现很多,答案会更长。直接的答案是,在索引到指针(*p)之前,需要取消对它的引用;看,我想找到节数、行数、元音数、辅音数、标点符号等…在上面的代码中,你是否看到
[[]字符串{…}
传递到NewPoem()
是一个好方法?@overexchange-就设计而言,这些都是“只读”操作,因此在创建后你不需要修改诗歌。因此,您可以使Poem
成为不可变的类型(这意味着您可以“免费”获得大量额外的好处)。这是您不使用指针的另一个原因。是的,指针类型被传递或返回以改变数据。我会附加一节later@overexchange-我将编辑我的答案来讨论[]]字符串{…}
这件事,因为注释可能不是最好的地方。@overexchange-即使您想在以后附加一节,也可能不需要指针。您可以改为使用如下内容:func(p-Poem)AddStanza(s-Stanza)Poem{…}
,它将返回一个新的、不可变的Poem,并带有额外的节。然后像这样使用它:var p Poem。。。;P