golang学习笔记——结构体嵌套接口

文章目录

  • 结构体嵌套接口
    • 结构体嵌套结构体
    • 结构体实现接口
    • 接口嵌套接口
    • 结构体嵌套接口
      • 例子1
      • 例子2
  • 总结
  • 参考资料

结构体嵌套接口

今天看k8s client-go源码时发现,结构体嵌套接口的现象。

// deployments implements DeploymentInterface
type deployments struct {client rest.Interfacens     string
}

之前的学习都是以下情况,

结构体嵌套结构体

type Address struct {City  stringState string
}type Person struct {Name    stringAge     intAddress // 结构体嵌套
}

通过组合的方式,增强了结构体的功能

结构体实现接口

package mainimport "fmt"type Writer interface {Write(string)
}type ConsoleWriter struct{}func (cw ConsoleWriter) Write(data string) {fmt.Println("Writing:", data)
}type Logger struct {Writer // 接口嵌入
}func main() {logger := Logger{Writer: ConsoleWriter{}}logger.Write("Hello, world!")
}

最常见的情况,相当了实现了一个接口的对象

接口嵌套接口

type Name interface {WriteName(name string)
}type Number interface {WriteNumber(number string)
}type Person interface {NameNumberHello()
}type person struct {name   stringnumber string
}func (p *person) WriteName(name string) {p.name = name
}func (p *person) WriteNumber(number string) {p.number = number
}func (p person) Hello() {fmt.Println("hello")
}func main() {p := person{}fmt.Println("Person:", p.name, p.number)p.WriteName("DoveOne")p.WriteNumber("1")p.Hello()fmt.Println("Person:", p.name, p.number)
}

增强了接口的方法集

结构体嵌套接口

例子1

package mainimport "fmt"type HelloWorld interface {Hello()
}type Person1 struct {Name       stringNumber     stringHelloWorld //匿名字段
}type Person2 struct {Name   stringNumber stringtag    HelloWorld //非匿名字段
}type hello struct {
}func (h hello) Hello() {fmt.Println("hello")
}func main() {h := hello{}p1 := &Person1{"DoveOne", "1", h}p1.Hello()p1.HelloWorld.Hello()p2 := &Person2{"DoveOne", "1", h}p2.tag.Hello() //非匿名字段必须指定字段名才能引用字段的方法
}

输出

hello
hello
hello

例子2

package mainimport ("fmt"
)type Interface interface {Len() intLess(i, j int) boolSwap(i, j int)
}// Array 实现Interface接口
type Array []intfunc (arr Array) Len() int {return len(arr)
}func (arr Array) Less(i, j int) bool {return arr[i] < arr[j]
}func (arr Array) Swap(i, j int) {arr[i], arr[j] = arr[j], arr[i]
}// 匿名接口(anonymous interface)
type reverse struct {Interface
}// 重写(override)
func (r reverse) Less(i, j int) bool {return r.Interface.Less(j, i)
}// 构造reverse Interface
func Reverse(data Interface) Interface {return &reverse{data}
}func main() {arr := Array{1, 2, 3}rarr := Reverse(arr)fmt.Println(arr.Less(0,1))fmt.Println(rarr.Less(0,1))
}

sort包中这么写的目的是为了重写Interface的Less方法,并有效利用了原始的Less方法;通过Reverse可以从Interface构造出一个反向的Interface。go语言利用组合的特性,寥寥几行代码就实现了重写。

对比一下传统的组合匿名结构体实现重写的写法,或许可以更好的帮助我们了解匿名接口的优点:

package mainimport ("fmt"
)type Interface interface {Len() intLess(i, j int) boolSwap(i, j int)
}type Array []intfunc (arr Array) Len() int {return len(arr)
}func (arr Array) Less(i, j int) bool {return arr[i] < arr[j]
}func (arr Array) Swap(i, j int) {arr[i], arr[j] = arr[j], arr[i]
}// 匿名struct
type reverse struct {Array
}// 重写
func (r reverse) Less(i, j int) bool {return r.Array.Less(j, i)
}// 构造reverse Interface
func Reverse(data Array) Interface {return &reverse{data}
}func main() {arr := Array{1, 2, 3}rarr := Reverse(arr)fmt.Println(arr.Less(0, 1))fmt.Println(rarr.Less(0, 1))
}

上面这个例子使用了匿名结构体的写法,和之前匿名接口的写法实现了同样的重写功能,甚至非常相似。但是仔细对比一下你就会发现匿名接口的优点,匿名接口的方式不依赖具体实现,可以对任意实现了该接口的类型进行重写。这在写一些公共库时会非常有用,如果你经常看一些库的源码,匿名接口的写法应该会很眼熟。

采用传统的组合匿名结构体方式,代码中的reverse 结构体与Array耦合

type reverse struct {Array
}

采用匿名接口(anonymous interface)的方式,可以对任意实现了该接口的类型进行重写

type reverse struct {Interface
}

匿名接口还有一个作用就是对结构体添加一些约束,必须使用实现了该接口的类型来构造实例。结构体中可以包含一些其他的字段,而interface只有方法,没有field。

package mainimport ("fmt""reflect""sort"
)type Array1 []intfunc (arr Array1) Len() int {return len(arr)
}func (arr Array1) Less(i, j int) bool {return arr[i] < arr[j]
}func (arr Array1) Swap(i, j int) {arr[i], arr[j] = arr[j], arr[i]
}type Array2 []intfunc (arr Array2) Len() int {return len(arr)
}func (arr Array2) Less(i, j int) bool {return arr[i] < arr[j]
}func (arr Array2) Swap(i, j int) {arr[i], arr[j] = arr[j], arr[i]
}type Sortable struct {sort.Interface// other fieldType string
}func NewSortable(i sort.Interface) Sortable {t := reflect.TypeOf(i).String()return Sortable{Interface: i,Type:      t,}
}func DoSomething(s Sortable) {fmt.Println(s.Type)fmt.Println(s.Len())fmt.Println(s.Less(0, 1))
}func main() {arr1 := Array1{1, 2, 3}arr2 := Array2{3, 2, 1, 0}DoSomething(NewSortable(arr1))DoSomething(NewSortable(arr2))
}

总结

在Go语言中,结构体嵌入接口(embedding an interface in a struct)是一种将接口作为结构体字段的方式。但是,这里的“嵌入”与传统的字段嵌入稍有不同,因为接口本身不包含任何数据,只包含一组方法的签名。

当你在结构体中嵌入一个接口时,你实际上是在声明该结构体必须实现该接口的所有方法。这并不是说接口被“嵌入”到结构体中,而是说结构体承诺它将满足该接口的方法集。

参考资料

golang中结构体嵌套接口
Go语言结构体进阶
无风—interface 作为 struct field,谈谈 Golang 结构体中的匿名接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/28557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gt9x双击唤醒屏幕

里面可以看到irq 和 rst的gpio引脚从设备树获取失败&#xff0c;排查设备树发现是属性名写错了&#xff1a; c &i2c1 {status "okay";goodix_ts5d {compatible "goodix,gt9xx";reg <0x5d>;// tp-size <89>;touchscreen-size-x <12…

Go Goroutine 究竟可以开多少?(详细介绍)

Go Goroutine 究竟可以开多少&#xff1f; Go语言因其高效的并发处理能力而备受欢迎&#xff0c;而Goroutine则是Go语言实现并发编程的核心。Goroutine比传统的线程更加轻量&#xff0c;允许开发者轻松地处理大量并发任务。那么&#xff0c;Go语言中的Goroutine究竟可以开多少…

6.1触发器的创建、删除和使用

6.1.1 触发器概述 触发器是一个被指定关联到表的数据库对象&#xff0c;与表的关系密切&#xff0c;不需要用户调用&#xff0c;在一个表的特定事件出现时将会被激活&#xff0c;此时某些MySql语句会自动执行。 触发器用于实现数据库的完整性&#xff0c;具有以下特点&#xff…

深入了解RSA加密算法

目录 前言 一、什么是RSA&#xff1f; 二、RSA加密的基本概念 1.非对称加密 2.密钥生成 3.加密和解密 三、RSA加密的工作原理 四、RSA的应用场景 五、RSA加密解密的实现 六、RSA算法的局限性及改进措施 前言 在当今的数字化时代&#xff0c;信息的安全性成为了人们关注…

密码学-密码协议之零知识证明

一、前言 零知识证明实际上一种密码协议&#xff0c;该协议的一方称为证明者(Prover)&#xff0c;通常用P表示&#xff0c;协议的另一方是验证者(Verifier)&#xff0c;一般用V表示。零知识证明是指P试图使V相信某个论断是正确的&#xff0c;但却不向V提供任何有用的信息&…

Photoshop中图像美化工具的应用

Photoshop中图像美化工具的应用 Photoshop中的裁剪工具Photoshop中的修饰工具模糊工具锐化工具涂抹工具 Photoshop中的颜色调整工具减淡工具加深工具海绵工具 Photoshop中的修复工具仿制图章工具污点修复画笔工具修复画笔工具修补工具内容感知移动工具红眼工具 Photoshop中的裁…

【杂记-浅谈以太网IP数据帧】

一、以太网数据帧 以太网数据帧是网络通信的基础单元&#xff0c;遵循IEEE 802.3标准&#xff0c;用于在以太网中传输数据。一个典型的以太网数据帧包括前导码、帧开始符、目的MAC地址、源MAC地址、类型或长度字段、数据载荷和帧校验序列。其中&#xff0c;类型字段指明了上层…

数据可视化:让数据讲述故事

数据可视化&#xff1a;让数据讲述故事 引言 在信息爆炸的时代&#xff0c;数据无处不在。然而&#xff0c;数据本身并不直观&#xff0c;很难从中直接获取有价值的信息。数据可视化作为一种强大的工具&#xff0c;能够帮助我们揭示数据背后的故事&#xff0c;让我们以更直观…

Spring Boot顶层接口实现类注入项目的方法

1、背景 在项目中&#xff0c;我们通常会具有同一特性的业务类定义一个顶层接口&#xff0c;让业务类实现这个接口&#xff0c;通过接口规范来管理这些类。我们将这些实现接口的业务类交托给Spring容器接口后&#xff0c;有时候需要根据业务类型来选择动态选择对应的业务类阿里…

尚品汇-(二)

一&#xff1a;环境安装 1.安装JAVA 运行环境 第一步&#xff1a;上传或下载安装包 cd /usr/local jdk-8u152-linux-x64.tar.gz 第二步&#xff1a;解压安装包 tar -zxvf jdk-8u152-linux-x64.tar.gz 第三步&#xff1a;建立软连接&#xff08;快捷方式&#xff09; ln -…

SpringBoot配置第三方专业缓存技术Redis

Redis缓存技术 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存中数据结构存储系统&#xff0c;通常用作数据库、缓存和消息中间件。它支持多种数据结构&#xff0c;如字符串、哈希表、列表、集合、有序集合等&#xff0c;并提供了丰富的功能和灵活的…

4.1 初探Spring Boot

初探Spring Boot实战概述 Spring Boot简介 Spring Boot是一个开源的Java框架&#xff0c;由Pivotal团队&#xff08;现为VMware的一部分&#xff09;开发&#xff0c;旨在简化Spring应用程序的创建和部署过程。它通过提供一系列自动化配置、独立运行的特性和微服务支持&#…

类加载的初始化阶段的奥秘

一、概述 初始化阶段是类加载机制&#xff08;加载&#xff0c;链接&#xff08;验证&#xff0c;准备&#xff0c;解析&#xff09;&#xff0c;初始化&#xff09;的最后一步。在准备阶段已经为类变量赋过一次值&#xff08;默认为0或null&#xff09;。在初始化阶段&#xf…

HTML和CSS基础(一)

前言 HTML&#xff08;HyperText Markup Language&#xff09;是一种用于创建网页的标准标记语言。它由各种标签组成&#xff0c;这些标签定义了网页的结构和内容。HTML的早期形式诞生于1989年&#xff0c;由CERN的物理学家Tim Berners-Lee发明&#xff0c;最初用于在科学家之…

js 刷题常用方法

Object 对象共有 toString()valueOf()obj.keys()obj.values()obj.entries()for of 循环…扩展运算符Array.of()Array.from() 数组使用时 toString 返回以逗号分隔的字符串valueOf 返回数组本身 Array 数组 创建数组 Array.from(可迭代对象)Array.of(传入一组参数) let arr…

C语言 | Leetcode C语言题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {if (headA NULL || headB NULL) {return NULL;}struct ListNode *pA headA, *pB headB;while (pA ! pB) {pA pA NULL ? headB : pA->ne…

windows11 x64 23H2 企业纯净版2024.6.16

闲来无事试安装了下da_nao_yan的 【6月12日更新】Windows11 22631.3737企业版 23H2 自用优化版 &#xff08;原版地址&#xff1a;https://bbs.pcbeta.com/viewthread-1985546-1-1.html&#xff09;&#xff0c;感觉比原版流畅多了&#xff0c;重新按照自己习惯封装了下&#x…

C++作业第四天

#include <iostream> using namespace std; class Per { private: string name; int age; int *high; double *weight; public: //构造函数 Per() { cout << "Per的无参构造" << endl; } Per(str…

Python获取一个列表的全组合

numList [1, 3, 5, 7, 9] from itertools import combinationsfor i in range(1, len(numList) 1): # xrange will return the values 1,2,3,4 in this loopprint(list(combinations(numList, i)))输出&#xff1a; [(1,), (3,), (5,), (7,), (9,)] [(1, 3), (1, 5), (1, 7)…

通讯的一些基本概念 -网卡 -网段 -网桥 -路由表

网卡&#xff08;Network Interface Card, NIC&#xff09; 网卡是安装在计算机或其他设备上的硬件组件&#xff0c;它允许设备通过有线或无线方式连接到计算机网络。网卡工作在OSI模型的数据链路层&#xff08;第二层&#xff09;和物理层&#xff08;第一层&#xff09;&…