Golang中为什么指针类型(如*S)不被视为定义类型?
Golang中为什么指针类型(如*S)不被视为定义类型?
我想知道为什么 *S 不是一个已定义类型,而 S 是。请看这个例子:
package main
import "fmt"
type S struct {}
type SType S // SType 和 S 不能互换使用。
type SPtrType *S // SPtrType 和 *S 可以互换使用,因为 *S 不是一个已定义类型。
func funcPtrS(ptrS *S) { fmt.Printf("funcPtrS's parameter has type: %T \n", ptrS) }
func funcSPtrType(sPtrType SPtrType) { fmt.Printf("funcSPtrType's parameter has type: %T \n", sPtrType) }
func main() {
var s S = S{}
fmt.Printf("s has type: %T \n", s)
var sType SType = SType(s) // 需要强制转换,因为 S 和 SType 都是已定义类型。
fmt.Printf("sType has type: %T \n", sType)
var ptrS *S = &s
fmt.Printf("ptrS has type: %T \n", ptrS)
var sPtrType SPtrType = ptrS // 不需要强制转换。*S 不是一个已定义类型。
fmt.Printf("sPtrType has type: %T \n", sPtrType)
funcPtrS(ptrS)
funcPtrS(sPtrType) // sPtrType 可以赋值给 *S,因为 *S 不是一个已定义类型。
funcSPtrType(ptrS) // ptrS 可以赋值给 SPtrType,因为 *S 不是一个已定义类型。
funcSPtrType(sPtrType)
}
/*
输出:
s has type: main.S
sType has type: main.SType
ptrS has type: *main.S
sPtrType has type: main.SPtrType
funcPtrS's parameter has type: *main.S
funcPtrS's parameter has type: *main.S
funcSPtrType's parameter has type: main.SPtrType
funcSPtrType's parameter has type: main.SPtrType
*/
这些文档 指出:
如果满足以下条件之一,则值 x 可被赋值给类型为 T 的变量("x 可赋值给 T"):
x的类型与T相同。x的类型V和T具有相同的基础类型,并且V或T中至少有一个不是已定义类型。
因此,我不能将类型为 main.S 的变量赋值给类型为 main.SType 的变量,因为这两种类型都是已定义类型。我可以将类型为 *main.S 的变量赋值给类型为 main.SPtrType 的变量,反之亦然,无需强制转换,因为 *main.S 不是一个已定义类型。
我不理解的是为什么 main.S 是一个已定义类型,而 *main.S 不是。
更多关于Golang中为什么指针类型(如*S)不被视为定义类型?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我明白了。S 是一个已定义类型,但 struct {} 不是一个已定义类型,就像 SPtrType 是一个已定义类型但 *S 不是一个已定义类型一样。你不能将 S 赋值给 SType 的原因是它们两者都是已定义类型。你可以将 *S 赋值给 SPtrType 的原因是这两个类型中只有一个是已定义类型(类型 SPtrType)。
以下是一个示例来说明这一点:
package main
import "fmt"
type S struct {A int} // 可以与 struct {A int} 互换使用
func func1(s1 struct {A int}) { fmt.Printf("func1的参数类型为: %T \n", s1) }
func func2(s2 S) { fmt.Printf("func2的参数类型为: %T \n", s2) }
func main() {
var s1 struct {A int} = struct {A int}{A: 1}
fmt.Printf("s1的类型为: %T \n", s1)
var s2 S = struct {A int}{A: 2}
fmt.Printf("s2的类型为: %T \n", s2)
func1(s1)
func1(s2) // 无需类型转换,因为 struct {A int} 不是一个已定义类型。
func2(s1) // 无需类型转换,因为 struct {A int} 不是一个已定义类型。
func2(s2)
}
/*
输出:
s1的类型为: struct { A int }
s2的类型为: main.S
func1的参数类型为: struct { A int }
func1的参数类型为: struct { A int }
func2的参数类型为: main.S
func2的参数类型为: main.S
*/
在上面的例子中,struct {A int} 不是一个已定义类型,但 S 是一个已定义类型,因此我可以在它们之间相互赋值而无需进行类型转换。
更多关于Golang中为什么指针类型(如*S)不被视为定义类型?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言规范中,定义类型(defined type) 是通过类型声明(type关键字)创建的类型。S是通过type S struct{}声明的定义类型,而*S是类型字面量(type literal),不是定义类型。
根据规范,*S是指针类型字面量,它由现有的类型S派生而来,但没有独立的类型标识。SPtrType是通过type SPtrType *S创建的定义类型,它和*S共享相同的基础类型(underlying type)*S。
由于赋值规则允许在至少一个类型不是定义类型时进行隐式转换,*S和SPtrType可以互换赋值。以下是示例:
package main
import "fmt"
type S struct{ X int }
type SPtrType *S
func main() {
var s S = S{X: 1}
var p1 *S = &s // p1 的类型是 *S(类型字面量)
var p2 SPtrType = &s // p2 的类型是 SPtrType(定义类型)
// 隐式赋值:*S 不是定义类型,SPtrType 是定义类型
p1 = p2 // 允许
p2 = p1 // 允许
// 类型检查
fmt.Printf("p1 type: %T\n", p1) // *main.S
fmt.Printf("p2 type: %T\n", p2) // main.SPtrType
// 通过指针修改值
p1.X = 2
fmt.Println(s.X) // 输出 2
p2.X = 3
fmt.Println(s.X) // 输出 3
}
输出:
p1 type: *main.S
p2 type: main.SPtrType
2
3
关键点:
*S是类型字面量,不是定义类型。SPtrType是定义类型,基础类型为*S。- 赋值兼容性基于规范中的规则:当至少一个类型不是定义类型时,相同基础类型的值可以互换。

