Go语言中Struct与继承与匿名字段和内嵌结构体全面详解

目录
  • 定义
  • 内嵌结构体

在golang中,采用匿名结构体字段来模拟继承关系。这个时候,可以说 Student 是继承自 Person .

type Person struct {
    name string
    age int
    sex string
}
func (Person) SayHello(){
 fmt.Println("this is from Person")
}
type Student struct {
    Person
    school string
}
func main() {
    stu := Student{school:"middle"}
    stu.name = "leo"
    stu.age = 30
    fmt.Println(stu.name) //这里其实就是这样做了一层转换stu.Person.name
    stu.SayHello() //也做了转换
}

可以看到继承之后的结构体拥有继承结构体的属性和方法。其实本质上是嵌套关系,它帮你简化了。

定义

结构体可以包含一个或多个 匿名(或内嵌)字段,即这些字段没有显式的名字,只有字段的类型是必须的,此时类型就是字段的名字。匿名字段本身可以是一个结构体类型,即 结构体可以包含内嵌结构体。

可以粗略地将这个和面向对象语言中的继承概念相比较,随后将会看到它被用来模拟类似继承的行为。Go 语言中的继承是通过内嵌或组合来实现的,所以可以说,在 Go 语言中,相比较于继承,组合更受青睐。

考虑如下的程序:

package main
import "fmt"
type innerS struct {
    in1 int
    in2 int
}
type outerS struct {
    b    int
    c    float32
    int  // anonymous field
    innerS //anonymous field
}
func main() {
    outer := new(outerS)
    outer.b = 6
    outer.c = 7.5
    outer.int = 60
    outer.in1 = 5
    outer.in2 = 10
    fmt.Printf("outer.b is: %d\n", outer.b)
    fmt.Printf("outer.c is: %f\n", outer.c)
    fmt.Printf("outer.int is: %d\n", outer.int)
    fmt.Printf("outer.in1 is: %d\n", outer.in1)
    fmt.Printf("outer.in2 is: %d\n", outer.in2)
    // 使用结构体字面量
    outer2 := outerS{6, 7.5, 60, innerS{5, 10}}
    fmt.Println("outer2 is:", outer2)
}

输出:

outer.b is: 6
outer.c is: 7.500000
outer.int is: 60
outer.in1 is: 5
outer.in2 is: 10
outer2 is:{6 7.5 60 {5 10}}

通过类型 outer.int 的名字来获取存储在匿名字段中的数据,于是可以得出一个结论:在一个结构体中对于每一种数据类型只能有一个匿名字段。

内嵌结构体

同样地结构体也是一种数据类型,所以它也可以作为一个匿名字段来使用,如同上面例子中那样。外层结构体通过 outer.in1 直接进入内层结构体的字段,内嵌结构体甚至可以来自其他包。内层结构体被简单的插入或者内嵌进外层结构体。这个简单的 “继承” 机制提供了一种方式,使得可以从另外一个或一些类型继承部分或全部实现。

另外一个例子:

示例 10.9 embedd_struct.go

package main
import "fmt"
type A struct {
    ax, ay int
}
type B struct {
    A
    bx, by float32
}
func main() {
    b := B{A{1, 2}, 3.0, 4.0}
    fmt.Println(b.ax, b.ay, b.bx, b.by)
    fmt.Println(b.A)
}

输出:

1 2 3 4
{1 2}

命名冲突

当两个字段拥有相同的名字(可能是继承来的名字)时该怎么办呢?

  • 外层名字会覆盖内层名字(但是两者的内存空间都保留),这提供了一种重载字段或方法的方式;
  • 如果相同的名字在同一级别出现了两次,如果这个名字被程序使用了,将会引发一个错误(不使用没关系)。没有办法来解决这种问题引起的二义性,必须由程序员自己修正。

例子:

type A struct {a int}
type B struct {a, b int}
type C struct {A; B}
var c C

规则 2:使用 c.a 是错误的,到底是 c.A.a 还是 c.B.a 呢?会导致编译器错误:ambiguous DOT reference c.a disambiguate with either c.A.a or c.B.a。

type D struct {B; b float32}
var d D

规则 1:使用 d.b 是没问题的:它是 float32,而不是 B 的 b。如果想要内层的 b 可以通过 d.B.b 得到。

到此这篇关于Go语言中Struct继承与匿名字段和内嵌结构体全面详解的文章就介绍到这了,更多相关Go Struct继承内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Go语言中的Struct结构体

    一.Struct结构体 Go语言中没有像C#.Java一样的Class,只有Struct这样的结构体.Go语言使用type关键字来定义一个类型. 如下: type User struct { Name string Age int32 Sex int16 AvatarUrl string } 二.Struct的声明以及初始化 初始化方法一:直接定义,通过变量名.成员名的方式赋值 //初始化方法1 var user1 User user1.Name = "BigOrange" user1

  • Go语言类型内嵌和结构体内嵌的具体使用

    目录 内嵌结构体 结构内嵌特性 结构体可以包含一个或多个匿名(或内嵌)字段,即这些字段没有显式的名字,只有字段的类型是必须的,此时类型也就是字段的名字.匿名字段本身可以是一个结构体类型,即结构体可以包含内嵌结构体. 可以粗略地将这个和面向对象语言中的继承概念相比较,随后将会看到它被用来模拟类似继承的行为.Go语言中的继承是通过内嵌或组合来实现的,所以可以说,在Go语言中,相比较于继承,组合更受青睐. 考虑如下的程序: package main import "fmt" type inn

  • Golang实现不被复制的结构体的方法

    目录 不允许复制的结构体 实现原理 结论 不允许复制的结构体 sync包中的许多结构都是不允许拷贝的,比如sync.Cond,sync.WaitGroup,sync.Pool, 以及sync包中的各种锁,因为它们自身存储了一些状态(比如等待者的数量),如果你尝试复制这些结构体: var wg1 sync.WaitGroup wg2 := wg1 // 将 wg1 复制一份,命名为 wg2 // ... 那么你将在你的 IDE 中看到一个醒目的警告: assignment copies lock

  • golang中结构体嵌套接口的实现

    在golang中结构体A嵌套另一个结构体B见的很多,可以扩展A的能力. A不仅拥有了B的属性,还拥有了B的方法,这里面还有一个字段提升的概念. 示例: package main import "fmt" type Worker struct {     Name string     Age int     Salary } func (w Worker) fun1() {     fmt.Println("Worker fun1") } type Salary s

  • 一文教你如何快速学会Go的struct数据类型

    目录 什么是结构体 创建结构体 创建匿名结构体 访问结构体字段 结构体零值 结构体指针 匿名字段 结构体嵌套 字段升级 结构体导出 结构体比较 什么是结构体 结构是表示字段集合的用户定义类型.它可以用于将数据分组为单个单元而不是将每个数据作为单独的值的地方. 例如,员工有firstName.lastName和age.将这三个属性分组到一个名为Employee. type Employee struct { firstName string lastName string age int } 上面

  • Go Struct结构体的具体实现

    目录 什么是结构体 1. 基本实例化(方法1) 2. new实例化(方法2) 3. 键值对初始化(方法3 结构体能够使用指针就使用指针) 结构体方法和接收者 encoding-json包 1. struct与json 2. struct tag 什么是结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.(继承,多态,封装) Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 1. 基本实例化(方法1) 只有当结构体实例化时,才会真正地分配内存(其实也就

  • Go语言中Struct与继承与匿名字段和内嵌结构体全面详解

    目录 定义 内嵌结构体 在golang中,采用匿名结构体字段来模拟继承关系.这个时候,可以说 Student 是继承自 Person . type Person struct { name string age int sex string } func (Person) SayHello(){ fmt.Println("this is from Person") } type Student struct { Person school string } func main() {

  • Go语言中struct的匿名属性特征实例分析

    本文实例分析了Go语言中struct的匿名属性特征.分享给大家供大家参考.具体分析如下: Go语言中struct的属性可以没有名字而只有类型,使用时类型即为属性名.(因此,一个struct中同一个类型的匿名属性只能有一个) 复制代码 代码如下: type PersonC struct {      id      int      country string  }    //匿名属性  type Worker struct {      //如果Worker有属性id,则worker.id表示

  • Kotlin 匿名类实现接口和抽象类的区别详解

    我就废话不多说了,还是上代码吧 接口: interface OnBind { fun onBindChildViewData(holder: String, itemData: Any, position: Int) } lesson.does(object : OnBind { override fun onBindChildViewData(holder: String, itemData: Any, position: Int) { println(holder + itemData +

  • C++继承中的对象构造与析构和赋值重载详解

    目录 一.构造/析构顺序及继承性 二.拷贝构造的继承性 三.赋值重载不具有继承性 总结 一.构造/析构顺序及继承性 class A { private: int _a; public: A(int a = 0): _a(a) { cout << "A()" << this << endl; } ~A() { cout << "~A()"<< this <<endl; } }; class B :

  • go语言数组及结构体继承和初始化示例解析

    目录 分类 数组 数组定义 结构体 结构体继承 结构体初始化 成员的操作 同名字段 其它匿名字段 非结构体类型 结构体指针类型 结构体字段实现接口 分类 类型 名称 长度 默认值 说明 pointer 指针   nil   array 数组   0   slice 切片   nil 引⽤类型 map 字典   nil 引⽤类型 struct 结构体       数组 如果要存储班级里所有学生的数学成绩,应该怎样存储呢?可能有同学说,通过定义变量来存储.但是,问题是班级有80个学生,那么要定义80

  • 详解go语言中type关键词的几种使用

    type是go语法里的重要而且常用的关键字,type绝不只是对应于C/C++中的typedef.搞清楚type的使用,就容易理解go语言中的核心概念struct.interface.函数等的使用.以下我用例子代码总结描述,请特别留意代码中的注释. 1.定义结构体 //结构体定义 type person struct { name string //注意后面不能有逗号 age int } func main() { //结构体初始化 p := person{ name: "taozs",

  • Go语言中slice作为参数传递时遇到的一些“坑”

    前言 相信看到这个题目,可能大家都觉得是一个老生常谈的月经topic了.一直以来其实把握一个"值传递"基本上就能理解各种情况了,不过最近遇到了更深一点的"小坑",与大家分享一下. 首先还是从最简单的说起,看下面代码: func main() { a := []int{7,8,9} fmt.Printf("len: %d cap:%d data:%+v\n", len(a), cap(a), a) ap(a) fmt.Printf("le

  • C语言中typedef的用法以及#define区别详解

    目录 1.简洁定义 2.为已有类型起别名 为字符数组起别名 为指针起别名 3.typedef 和 #define 的区别 总结 1.简洁定义 C语言允许为一个数据类型起一个新的别名,就像给人起"绰号"一样.而编程中起别名,是为了编程人员编程方便,例如: 定义如下结构体 struct stu { int ID; char name[20]; float score[3]; char *data; }; 要想定义一个结构体变量就得这样写: struct stu Marry://Marry是

  • 深入了解Go语言中goioc框架的使用

    目录 goioc 介绍 快速上手 接口介绍 使用 goioc 如何使用 生命周期 实例化 获取对象 结构体字段依赖注入 反射形式使用 goioc 如何使用 接口.结构体.结构体指针 不会自动注入本身 goioc 介绍 goioc 是一个基于 GO 语言编写的依赖注入框架,基于反射来进行编写. 支持泛型: 简单易用的 API: 简易版本的对象生命周期管理,作用域内对象具有生命: 延迟加载,在需要的时候才会实例化对象: 支持结构体字段注入,多层注入: 对象实例化线程安全,作用域内只会被执行一次. 下

  • C语言 struct结构体超详细讲解

    目录 一.本章重点 二.创建结构体 三.typedef与结构体的渊源 四.匿名结构体 五.结构体大小 六.结构体指针 七.其他 一.本章重点 创建结构体 typedef与结构体的渊源 匿名结构体 结构体大小 结构体指针 其他 二.创建结构体 先来个简单的结构体创建 这就是一个比较标准的结构体 struct people { int age; int id; char address[10]; char sex[5]; };//不要少了分号. 需要注意的是不要少了分号. 那么这样创建结构体呢? s

随机推荐