Go 嵌入类型
文章转载地址: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 嵌入类型的更多相关文章
- Go语言嵌入类型
一.什么是嵌入类型 先看如下代码: type user struct { name string email string } type admin struct { user // Embedded ...
- Go 语言中的方法,接口和嵌入类型
https://studygolang.com/articles/1113 概述 在 Go 语言中,如果一个结构体和一个嵌入字段同时实现了相同的接口会发生什么呢?我们猜一下,可能有两个问题: 编译器会 ...
- golang拾遗:嵌入类型
这里是golang拾遗系列的第三篇,前两篇可以点击此处链接跳转: golang拾遗:为什么我们需要泛型 golang拾遗:指针和接口 今天我们要讨论的是golang中的嵌入类型(embedding t ...
- go接口及嵌入类型例子
书上看的.慢慢领会.. package main import ( "fmt" ) type notifier interface { notify() } type user s ...
- Go嵌入类型及内部提升样例
这个有点新鲜哟... package main import ( "fmt" ) type notifier interface { notify() } type user st ...
- [C#]嵌入互操作类型
嵌入互操作类型(Embed Interop Types) 运用office编程调用Excel 的PIA时Microsoft.Office.Interop.Excel.dll时会产生如下问题: 1.提示 ...
- Go语言规格说明书 之 接口类型(Interface types)
go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...
- 九.Protobuf3特殊类型
Protobuf3 Any类型 Any消息类型允许您将消息作为嵌入类型,而不需要它们 .proto定义.Any包含任意序列化的消息(字节),以及一个URL,该URL充当该消息的全局唯一标识符并解析为该 ...
- 学习Spring-Data-Jpa(五)---可嵌入对象和元素集合的使用
1.场景一:地址信息(省.市.县.详细地址)在很多实体中都需要,比如说作者有地址,订单也有地址,但是他们的地址并不能独立与他们存在,所以地址不能映射为实体,那么我们就需要在作者实体和订单实体中都添加这 ...
随机推荐
- es6下 vue实例属性template不能使用
esm模式下 不能使用template,需要引入非esm的vue.js,查看vue源码的包的dist目录下 文件标有esm是支持ems,没有标记,就是不支持(这个知识,怎么说了,应该属于webpack ...
- TCP/IP协议 网络层
IP协议介绍 1.IP协议是TCP/IP协议族中最为核心的协议.IP协议将多个包交换网络连接起来,它在源地址和目的地址之间传送一种称为数据包的东西,它还提供对数据大小的重新组装功能,以适应不同网络对包 ...
- 【Bad Practice】12306 query
- Oracle 11g R2性能优化 tkprof
另一篇博文总结了关于SQL TRACE工具的使用方式,但是产生的trace文件格式阅读起来并不是十分友好,为了更好的分析trace文件,Oracle也自带了一个格式化工具tkprof.tkprof工具 ...
- 深入了解webpack前,可以了解的小知识点。
阅读前:文章大概是写,简单用过webpack,想继续深入了解webpack前需要了解的知识.但文章内容跟webpack使用关系并不大. 文章概要: Object.defineProperty call ...
- 远程Gitlab新建的分支在IDEA里不显示
cmd命令打开dos命令窗口,进入项目文件所在目录 (**TIPS:在资源管理器的地址栏里直接输入cmd,就会打开命令窗口,并且此时命令窗口显示的路径就是当前路径)git branch -a:可以查看 ...
- Cache Aside Pattern
Cache Aside Pattern 即旁路缓存是缓存方案的经验实践,这个实践又分读实践,写实践 对于读请求 先读cache,再读db 如果,cache hit,则直接返回数据 如果,cache m ...
- Qt如何在QTabWidget上绘图
Qt绘图事件必须在paintEvent事件下绘图,这样导致我们在向Qt设计师界面上拖拽的控件绘图时,造成了很大的麻烦. 我们不能在拖拽的控件上写paintEvent函数,但是可以自定义一个类,继承某一 ...
- 监控单个进程占用cpu与内存的使用情况
#!/bin/bashinterval=1if [ "$1" != "" ]then interval=$1fiecho "检查时间间隔(单位秒):& ...
- python headers missing
系统环境 win7 64 bit,cygwin,Gvim8.1 问题 Gvim通过插件管理器Vundle下载好了YouCompleteMe插件的全部文件. 利用cygwin 进入在YouComplet ...