Go分配涉及自定义类型的指针

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

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规范:可赋值性中有定义。与你的情况相关的规则是:

VT具有相同的底层类型,并且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.

huangapple
  • 本文由 发表于 2022年4月9日 20:55:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/71808268.html
匿名

发表评论

匿名网友

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

确定