英文:
Go array for method
问题
我可以使用数组和指针作为Go方法吗?
我有以下代码:
var array = [3]string{"A", "B", "C"}
type arrayTypePt *[3]string
func (m *arrayTypePt) change() { m[1] = "W" }
func main() {
(arrayTypePt(&array)).changeArray4()
}
但是这段代码:http://play.golang.org/p/mXDEhmA9wk
给我一个错误:
invalid receiver type *arrayTypePt (arrayTypePt is a pointer type)
invalid operation: m[1] (type *arrayTypePt does not support indexing)
arrayTypePt(&array).changeArray4 undefined (type arrayTypePt has no field or method changeArray4)
当我尝试在切片中使用时,我得到相同的错误。
为什么我不能在方法中这样做?
英文:
Can I use array and its pointer for Go methods?
I have the following code:
var array = [3]string{"A", "B", "C"}
type arrayTypePt *[3]string
func (m *arrayTypePt) change() { m[1] = "W" }
func main() {
(arrayTypePt(&array)).changeArray4()
}
But this code: http://play.golang.org/p/mXDEhmA9wk
give me an error of:
invalid receiver type *arrayTypePt (arrayTypePt is a pointer type)
invalid operation: m[1] (type *arrayTypePt does not support indexing)
arrayTypePt(&array).changeArray4 undefined (type arrayTypePt has no field or method changeArray4)
I get the same error when I try this with slice.
Why I cannot do this in method?
答案1
得分: 7
方法的接收者类型不能是指向指针的指针,但你写的代码是这样的:
func (m *arrayTypePt) change() { m[1] = "W" }
arrayTypePt
已经是一个指针 *[3]string
。引用自语言规范:
接收者的类型必须是
T
或*T
(可能使用括号),其中T
是类型名。T
所表示的类型称为接收者的基本类型;它不能是指针类型或接口类型,并且必须在同一个包中声明。
你的第二个错误("type *arrayTypePt does not support indexing")也是由此引起的(m
是指向指针的指针,所以你不能对其进行索引;如果它只是指向数组或切片的指针,指针间接引用将是自动的)。
你的第三个错误只是一个拼写错误,你声明了一个名为 change()
而不是 changeArray4()
的方法。
所以你应该只给非指针数组类型命名:
type arrayType [3]string
并且可以直接使用这个类型声明你的数组:
var array = arrayType{"A", "B", "C"}
然后可以简单地调用它的 change()
方法:
array.change()
数组的地址将会自动获取(因为 change()
方法有一个指针接收者,但 array
变量本身不是指针)。
在Go Playground上尝试一下。
注意事项 / 替代方案
如果你希望你的 array
变量明确地是 [3]string
,你仍然可以通过将其转换为 arrayType
,将其设置为另一个变量,并在此变量上调用 change()
(因为作为变量,它的地址可以被获取,而像 arrayType(arr)
这样的转换的地址不能被获取):
arr2 := [3]string{"A", "B", "C"}
arr3 := arrayType(arr2)
arr3.change()
或者,如果你将变量声明为指向类型 [3]string
的指针,你可以节省所需的额外变量(这只是为了能够获取其地址):
arr4 := new([3]string)
*arr4 = [3]string{"A", "B", "C"}
((*arrayType)(arr4)).change()
在Go Playground上也尝试这些变体。
英文:
The receiver type of a method cannot be a pointer to a pointer, but that is what you wrote:
func (m *arrayTypePt) change() { m[1] = "W" }
arrayTypePt
is already a pointer *[3]string
. Quoting from the language specification:
> [The receiver] type must be of the form T
or *T
(possibly using parentheses) where T
is a type name. The type denoted by T
is called the receiver base type; it must not be a pointer or interface type and it must be declared in the same package as the method.
Your 2nd error ("type *arrayTypePt does not support indexing") is also a result of this (m
is a pointer to pointer, that's why you can't index it; if it would only be a pointer to array or slice, the pointer indirection would be automatic).
Your 3rd error is simply a typo, you declared a method named change()
and not changeArray4()
.
So you should only name the non-pointer array type:
type arrayType [3]string
And you can declare your array using directly this type:
var array = arrayType{"A", "B", "C"}
And you can simply call its change()
method:
array.change()
The address of the array will be taken automatically (because the change()
method has a pointer receiver but the array
variable itself is not a pointer).
Try it on the Go Playground.
Notes / Alternatives
If you would want your array
variable to be explicitly [3]string
, you could still make it work by converting it to arrayType
, setting it to another variable, and change()
can be called on this (because being a variable its address can be taken - while the address of a conversion like arrayType(arr)
cannot):
arr2 := [3]string{"A", "B", "C"}
arr3 := arrayType(arr2)
arr3.change()
Or if you would declare your variable to be a pointer to type [3]string
, you could save the required additional variable (which was only required so we were able to take its address):
arr4 := new([3]string)
*arr4 = [3]string{"A", "B", "C"}
((*arrayType)(arr4)).change()
Try these variants too on the Go Playground.
答案2
得分: 0
如果将数组/切片变量定义为接收器类型,它将正常工作:
type arrayType [3]string
var array arrayType = [3]string{"A", "B", "C"} # 注意这里的 "arrayType"
func (m *arrayType) change() { m[1] = "W" }
func main() {
array.change()
}
我不确定为什么类型转换会表现出这样的行为。
英文:
It works fine if you define the array/slice variable as the receiver type:
type arrayType [3]string
var array arrayType = [3]string{"A", "B", "C"} # note "arrayType" here
func (m *arrayType) change() { m[1] = "W" }
func main() {
array.change()
}
I'm not sure why the typecasting behaves like it does.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论