首页 > Golang继承指针与非指针的一个疑问

Golang继承指针与非指针的一个疑问

上述 结构 Persion 中 一个指针 Animal 和一个非指针的 Animal 两个有啥区别,分别应用在什么样的场合?

如果用于继承 指针的Animal 似乎就不正确了


题主,或许是你想太多了,指针嘛,就是一个传值还是传引用的区别,例如:

package main

import (
    "fmt"
)

type Animal struct {
    Name string
}
type Persion struct {
    Animal
}
type Ppersion struct {
    *Animal
}

func main() {
    animal := Animal{Name: "Cat"}
    persion := Persion{animal}
    ppersion := Ppersion{&animal}
    fmt.Println("Animal:" + animal.Name)
    fmt.Println("Persion:" + persion.Name)
    fmt.Println("PPersion:" + ppersion.Name)

    animal.Name = "Dog"
    fmt.Println("------------我是卖萌分割线------------")
    fmt.Println("Animal:" + animal.Name)
    fmt.Println("Persion:" + persion.Name)
    fmt.Println(persion.Animal == animal)
    fmt.Println("PPersion:" + ppersion.Name)
    fmt.Println(ppersion.Animal == &animal)
}

你可以看到如下输出

Animal:Cat
Persion:Cat
PPersion:Cat
------------我是卖萌分割线------------
Animal:Dog
Persion:Cat
false
PPersion:Dog
true

传值和传引用,显而易见,非指针匿名字段是原结构体的一个拷贝,不影响原结构体
这会带来很多问题,所有平时见到的,指针匿名字段多一些,当然有些场景下确实需要值传递。
关于对原结构体方法的引用,至少我没有发现有太大得区别,也许如楼上说的那样,也许是我想少了


用Animal无法调用接收者为 * Animal(这里是指针类型,编辑器有问题)的方法
用* Animal可以调用接收者为Animal与* Animal的方法
为什么?
因为go在编译的时候会为接收者为值类型的创造一个同类型的指针方法


Go 语言里面只有类型嵌入,没有类型继承,请题主要以Java等OOP语言的方式去思考Go的问题,在Go里面,第一等类型是函数类型…… 你这里所说的是嵌入类型:

结构体类型可以包含匿名或者嵌入字段。也叫做嵌入一个类型。当我们嵌入一个类型到结构体中时,该类型的名字充当了嵌入字段的字段名。

package main

import (
    "fmt"
)

type User struct {
    Name   string
    Gender string
}

func (user *User) Login() {
    fmt.Println("Login to the system")
}

type Manager struct {
    User
    Position string
}

func main() {
    manager := Manager{
        User: User{
            Name:   "某某某",
            Gender: "男",
        },
        Position: "超级管理员",
    }

    manager.Login()
}

上面代码中,我们定义了一个新类型 Manager 然后把 User 类型嵌入进去,注意这个不叫继承而叫组合。 User 类型跟 Manager 类型没有关系。

当我们嵌入一个类型,这个类型的方法就变成了外部类型的方法,但是当它被调用时,方法的接受者是内部类型(嵌入类型),而非外部类型。— Effective Go

因此嵌入类型的名字充当着字段名,同时嵌入类型作为内部类型存在,我们可以使用下面的调用方法:

manager.User.Login()

这儿我们通过类型名称来访问内部类型的字段和方法。然而,这些字段和方法也同样被提升到了外部类型:

manager.Login()

下面是 Go 语言中内部类型方法集提升的规则:

给定一个结构体类型 S 和一个命名为 T 的类型,方法提升像下面规定的这样被包含在结构体方法集中:

  1. 如果 S 包含一个匿名字段 T,S 和 *S 的方法集都包含接受者为 T 的方法提升。
  2. 对于 *S 类型的方法集包含接受者为 *T 的方法提升
  3. 如果 S 包含一个匿名字段 *T,S 和 *S 的方法集都包含接受者为 T 或者 *T 的方法提升
【热门文章】
【热门文章】