英文:
Go assignment involving pointers to custom types
问题
我正在使用自定义类型,并且在涉及指针的情况下遇到问题,就像下面的代码一样。
下面的代码是有效的:
package main
import (
"fmt"
)
type deck []string
func newDeck(cards ...string) deck {
return cards
}
下面的代码也是有效的:
package main
func str(n []string) *[]string {
return &n
}
而下面的代码是无效的。为什么呢?我必须编写一个类型转换,像return (*deck)(&cards)
这样。
package main
import (
"fmt"
)
type deck []string
func newDeck(cards ...string) *deck {
return &cards // 编译时需要写成 return (*deck)(&cards)
}
英文:
I am using custom types and I have a problem when pointers are involved like below.
Code below is valid:
package main
import (
"fmt"
)
type deck []string
func newDeck(cards ...string) deck {
return cards
}
Code below is valid too:
package main
func str(n []string) *[]string {
return &n
}
The below code instead is not valid. Why so? I have to write a type conversion like return (*deck)(&cards)
package main
import (
"fmt"
)
type deck []string
func newDeck(cards ...string) *deck {
return &cards // compiles with return (*deck)(&cards)
}
答案1
得分: 3
关于赋值(包括返回值)的规则在Go规范:可赋值性中有定义。与你的情况相关的规则是:
V
和T
具有相同的底层类型,并且V或T中至少有一个不是命名类型。
还有底层类型:
如果T是预声明的布尔、数值或字符串类型,或者是类型字面量,则相应的底层类型是T本身。
第一个示例编译通过,因为[]string
是一个具有底层类型[]string
(它本身)的未命名类型字面量,而deck
是一个具有底层类型[]string
(根据你的类型定义)的命名类型。
第二个示例无法编译,因为*[]string
和*deck
都是具有不同底层类型的未命名类型字面量。
要使第二个示例编译通过,你不能依赖直接赋值,但是,正如你发现的那样,可以使用显式类型转换:
return (*deck)(&cards)
这个转换是有效的,因为根据以下规则:
忽略结构标签(见下文),
x
的类型和T
都是指针类型,它们不是命名类型,并且它们的指针基础类型不是类型参数,但具有相同的底层类型。
英文:
The rules about assignments (including returns) are defined in the Go specs: Assignability. The one that is relevant to your case is:
> V
and T
have identical underlying types and at least one of V or T is not a named type.
And Underlying types:
> If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself.
The first example compiles because []string
is an unnamed type literal with underlying type []string
(itself) and deck
is a named type with underlying type []string
(by your type definition).
The second example does not compile because both *[]string
and *deck
are unnamed type literals with themselves as (different) underlying types.
To make the second example compile, you can't rely on a direct assignment, but, as you found out, use an explicit type conversion
return (*deck)(&cards)
And this conversion is valid due to the following rule:
> ignoring struct tags (see below), x
's type and T
are pointer types that are not named types, and their pointer base types are not type parameters but have identical underlying types.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论