文章转载地址:https://www.flysnow.org/2017/04/06/go-in-action-go-embedded-type.html

嵌入类型或嵌套类型,这是一种可以把已有类型的声明嵌入到新的类型里的一种方式,这种功能对代码复用非常

重要

在其他语言中,有继承的概念,但是在 Go 语言中没有继承的概念,Go 提倡的代码复用的方式是组合,所以,这

也是嵌入类型的意义所在,组合不是继承,所以,Go 才会更加灵活

type Reader interface {
Read(p []byte) (n int, err error)
} type Writer interface {
Write(p []byte) (n int,err error)
} type Closer interface {
Close() error
} type ReadWriter interface {
Reader
Writer
} type ReadCloser interface {
Reader
Closer
} type WriteCloser interface {
Writer
Closer
}

  上面是标准 io 包里,我们常用的接口,可以看到 ReadWriter 接口是嵌入 Reader、Writer 接口组合而成的新接口,这样

我们就不用在重复的定义被嵌入接口的方法,直接通过嵌入就可以了。嵌入类型同样适用于结构体类型,看下面例子:

type user struct {
name string
email string
} type admin struct {
user
level string
}

  嵌入后,被嵌入的类型称之为内部类型,新定义的类型称之为外部类型,这里 user 就是内部类型,而 admin 是外部类型

通过嵌入类型,与内部类型相关的字段、方法、标识符等都会被外部类型所拥有,就像外部类型自己的一样,这样就达到了

代码快捷复用组合的目的

同时,外部类型还可以添加自己的方法,字段等,可以很方便的扩展外部类型的功能

type user struct {
name string
email string
} type admin struct {
user
level string
} func main() {
ad := admin{user{"张三","zhangsans@qq.com"},"管理员"}
fmt.Println("可以直接调用,名字是:",ad.name)
fmt.Println("也可以通过内部类型调用:",ad.user.name)
fmt.Println("但新增的属性只能直接调用:",ad.level)
}

  上面是嵌入类型的使用,在初始化的时候,我们采用的是字面值的方式,先初始化 user 这个内部类型,再初始化

新增的 level 属性

对于内部类型的属性和方法访问上,我们可以采用外部类型直接访问,也可以通过内部类型进行访问,但是我们为

外部类型新增方法属性字段,只能使用外部类型访问,因为内部类型没有这些

当然,外部类型也可以声明同名的字段或方法,来覆盖内部类型,这种情况方法比较多,以方法为例:

type user struct {
name string
email string
} type admin struct {
user
level string
} func (u user) sayHello() {
fmt.Println("Hello,I am a user")
} func (a admin) sayHello() {
fmt.Println("Hello,I am a admin")
} func main() {
ad := admin{user{"张三","zhangsans@qq.com"},"管理员"}
ad.user.sayHello()
ad.sayHello()
}

  内部类型 user 有一个 sayHello 方法,外部类型对其进行了覆盖,同名重写 sayHello,然后在 main 方法分别访问这两个

类型的方法,打印输出:

Hello,I am a user
Hello,I am a admin

    从上面的输出可以看出,方法 sayHello 被覆盖了

嵌入类型还有一个强大的地方就是:如果内部类型实现了某个接口,那么外部类型也被认为实现了这个接口,如下示例:

type Hello interface {
hello()
} type user struct {
name string
email string
} type admin struct {
user
level string
} func (u user) hello() {
fmt.Println("Hello, I am a user")
} func sayHello(h Hello) {
h.hello()
} func main() {
ad := admin{user{"张三","zhangsans@qq.com"},"管理员"}
sayHello(ad.user) // 使用 user 作为参数
sayHello(ad) // 使用 admin 作为参数
}

  新增一个 Hello 接口,然后让 user 类型实现这个接口,最后定义了一个 sayHello 方法,它接受一个 Hello 类型的

参数,最后我们在 main 函数调用的时候,发现不管是 user 类型吧,还是 admin 类型作为参数传递给 sayHello 都能正

常调用,这里就能说名 admin 接口实现了接口 Hello,但是又没有显示声明 admin 实现,所以这个实现是通过内部类型

user 实现的,因为 admin 包含了 user 所有方法和字段,所以也就实现了这个接口

Go 嵌入类型的更多相关文章

  1. Go语言嵌入类型

    一.什么是嵌入类型 先看如下代码: type user struct { name string email string } type admin struct { user // Embedded ...

  2. Go 语言中的方法,接口和嵌入类型

    https://studygolang.com/articles/1113 概述 在 Go 语言中,如果一个结构体和一个嵌入字段同时实现了相同的接口会发生什么呢?我们猜一下,可能有两个问题: 编译器会 ...

  3. golang拾遗:嵌入类型

    这里是golang拾遗系列的第三篇,前两篇可以点击此处链接跳转: golang拾遗:为什么我们需要泛型 golang拾遗:指针和接口 今天我们要讨论的是golang中的嵌入类型(embedding t ...

  4. go接口及嵌入类型例子

    书上看的.慢慢领会.. package main import ( "fmt" ) type notifier interface { notify() } type user s ...

  5. Go嵌入类型及内部提升样例

    这个有点新鲜哟... package main import ( "fmt" ) type notifier interface { notify() } type user st ...

  6. [C#]嵌入互操作类型

    嵌入互操作类型(Embed Interop Types) 运用office编程调用Excel 的PIA时Microsoft.Office.Interop.Excel.dll时会产生如下问题: 1.提示 ...

  7. Go语言规格说明书 之 接口类型(Interface types)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的  ...

  8. 九.Protobuf3特殊类型

    Protobuf3 Any类型 Any消息类型允许您将消息作为嵌入类型,而不需要它们 .proto定义.Any包含任意序列化的消息(字节),以及一个URL,该URL充当该消息的全局唯一标识符并解析为该 ...

  9. 学习Spring-Data-Jpa(五)---可嵌入对象和元素集合的使用

    1.场景一:地址信息(省.市.县.详细地址)在很多实体中都需要,比如说作者有地址,订单也有地址,但是他们的地址并不能独立与他们存在,所以地址不能映射为实体,那么我们就需要在作者实体和订单实体中都添加这 ...

随机推荐

  1. SQL SERVER数据库附加是只读的解决方法

    使用sa登录SQL Server2008附加数据库,附加之后数据库为只读的, 点数据库-->“属性”-->“选项”-->“状态”, 发现“数据库为只读”这一项为True,改为fals ...

  2. jQuery通过ajax请求php遍历json数组到table中的代码

    html代码(test.html),js在html底部 具体代码如下所示: <!DOCTYPE html> <html lang="en"> <hea ...

  3. tesseract库

    1.简介 # -*-coding:utf8 -*- #图形验证码识别技术 ''' 阻碍我们爬虫的,有时候是在登录或者请求一些数据时候的图形验证码.因此这里我们讲解 一种能将图片翻译成文字的技术.将图片 ...

  4. 【Docker】-NO.132.Docker.1 -【Docker 修改容器端口】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  5. 用python脚本获取运行环境中的module 列表

    由于脚本运行在远程环境,总报错说一些module没有.所以决定彻底对环境进行一次摸底. 于是,用如下代码即可实现: #!/usr/bin/env python import sys try: #pri ...

  6. .Net Core部署IIS

    1.环境安装 https://dotnet.microsoft.com/download/dotnet-core 下载Runtime & Hosting Bundle包安装,iis模块会出现支 ...

  7. FB面经 Prepare: Even Tree

    You are given a tree (a simple connected graph with no cycles). The tree has nodes numbered from to ...

  8. Seq2Seq ---学习笔记

    应用场景:机器翻译 与language model 不同 MT model 的a<0> 是由encoder 生成的. language model 的 a<0> 是 初始化的. ...

  9. PHP 程序员危机(转载)

    感谢有这样的机会,能和大家一起来聊聊开发者的那些事儿. 其实程序员危机是一个真实存在的问题.也有人说是互联网行业的下滑或者互联网行业已过了风口等等.我在这儿主要谈的是 PHP 程序员的危机,而这种危机 ...

  10. RAID技术详解

    RAID:Redundant Array of Independent Disks 中文我们称为独立冗余磁盘阵列.基本上是见名知意.RAID的基本思想就是将多个容量较小且价格实惠的磁盘进行组合起来构成 ...