Go array for method

huangapple go评论76阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2015年6月1日 12:52:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/30565818.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定