Go语言中的接口设计艺术:发现面向对象编程的无限可能

一、GoLang 中的接口

1、GoLang 中的接口
  • 在 Go 语言中接口(interface)是一种类型,一种抽象的类型
  • 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节
  • 实现接口的条件
    • 一个对象只要全部实现了接口中的方法,那么就实现了这个接口
    • 换句话说,接口就是一个需要实现的方法列表
2、为什么要使用接口
  • 上面的代码中定义了猫和狗,然后它们都会叫,你会发现 main 函数中明显有重复的代码
  • 如果我们后续在加上猪,青蛙等动物的话,我们的代码还会一直重复下去
  • 那我们能不能把它们当成“能叫的动物”来处理呢?
package mainimport "fmt"type Cat struct {Name string
}func (c Cat) Say() string {return c.Name + ":喵喵喵"}type Dog struct {Name string
}func (d Dog) Say() string {return d.Name + ":汪汪汪"}func main() {c := Cat{Name: "小白猫"}    // 小白猫:喵喵喵fmt.Println(c.Say())d := Dog{"阿黄"}fmt.Println(d.Say())       // 阿黄: 汪汪汪
}
/*
小白猫:喵喵喵
阿黄: 汪汪汪*/
3、定义一个Usber 接口
  • 定义一个 Usber 接口让 Phone 和 Camera 结构实现这个接口
package mainimport "fmt"//1、接口是一个规范
type Usber interface {start()stop()
}//2、如果接口里面有方法的话,必要要通过结构体或者通过自定义类型实现这个接口
func (p Phone) start() {fmt.Println(p.Name, "启动")
}
func (p Phone) stop() {fmt.Println(p.Name, "关机")
}func main() {p := Phone{Name: "华为手机",}var p1 Usber   // golang中接口就是一个数据类型p1 = p       // 表示手机实现Usb接口p1.start()p1.stop()
}
/*
华为手机 启动
华为手机 关机*/
4、go 中类
  • Go 语言中没有类的概念,也不支持类的继承等面向对象的概念
  • Go 语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性

二、空接口

1、空接口说明
  • golang 中空接口也可以直接当做类型来使用,可以表示任意类型
  • Golang 中的接口可以不定义任何方法,没有定义任何方法的接口就是空接口
  • 空接口表示没有任何约束,因此任何类型变量都可以实现空接口
  • 空接口在实际项目中用的是非常多的,用空接口可以表示任意数据类型
2、空接口作为函数的参数
package mainimport "fmt"//空接口作为函数的参数
func show(a interface{}){fmt.Printf("值:%v 类型:%T\n",a,a)
}func main() {show(20)                      // 值:20 类型:intshow("你好golang")            // 值:你好golang 类型:stringslice := []int{1, 2, 34, 4}show(slice)                     // 值:[1 2 34 4] 类型:[]int
}
3、切片实现空接口
pakcage mainimport "fmt"func main() {var slice = []interface{}{"Snail", 20, true, 32.2}fmt.Println(slice)  // [Snail 20 true 32.2]
}
4、map 的值实现空接口
package mainimport "fmt"func main() {//空接口作为 map 值var studentInfo = make(map[string]interface{})studentInfo["name"] = "Snail"studentInfo["age"] = 18studentInfo["married"] = falsefmt.Println(studentInfo)// [age:18 married:false name: Snail]
}

三、类型断言

  • 一个接口的值(简称接口值)是由一个具体类型和具体类型的值两部分组成的
  • 这两部分分别称为接口的动态类型和动态值
  • 如果我们想要判断空接口中值的类型,那么这个时候就可以使用类型断言
  • 其语法格式:x.(T)
    • x:表示类型为interface{}的变量
    • T:表示断言x可能是的类型
package mainimport "fmt"func main() {var x interface{}x = "Hello GoLang"v,ok := x.(string)if ok {fmt.PrintIn(v)}else {fmt.PrintIn("非字符串类型")}
}

四、值接收者和指针接收者

1、值接收者
  • 当方法作用于类型接收者时,Go语言会在代码运行时将接收者的值复制一份
  • 在值类型接收者的方法中可以获取接收者的成员值,但修改操作只是针对副本,无法修改接收者变量本身
package mainimport "fmt"type Usb interface {Start()Stop()
}type Phone struct{Name string
}func (p Phone) Start(){fmt.PrintIn(p.Name,"开始工作")
}func (p Phone) Stop(){fmt.PrintIn(p.Name,"停止")
}func main() {phone1 := Phone{    //1、实例化值类型Name:"小米手机"}var p1 Usb = phone1    //phone1实现了Usb接口phone1是Phone类型p1.Start()phone2 := &Phone{	     // 二:实例化指针类型Name: "苹果手机",}var p2 Usb = phone2      //phone2 实现了 Usb 接口 pho}
2、指针接收者
  • 指针类型的接收者由一个结构体的指针组成
  • 由于指针的特性,调用方法时修改接收者指针的任意成员变量,在方法结束后,修改都是有效的
  • 这种方式就十分接近于其他语言中面向对象中的this或者self
  • 例如我们为Person添加一个SetAge方法,来修改实例变量的年龄
package main
import "fmt"
type Usb interface {Start()Stop()
}
type Phone struct {Name string
}
func (p *Phone) Start() {fmt.Println(p.Name, "开始工作")
}
func (p *Phone) Stop() {fmt.Println("phone 停止")
}
func main() {/*错误写法phone1 := Phone{Name: "小米手机",}var p1 Usb = phone1p1.Start()*///正确写法phone2 := &Phone{     // 指针类型接收者只能传入指针类型,不能传入值类型Name: "苹果手机",}var p2 Usb = phone2 //phone2 实现了 Usb 接口 phone2 是 *Phone 类型p2.Start()//苹果手机 开始工作
}
3、值类型接收者使用时机
  • 需要修改接收者中的值
  • 接收者是拷贝代价比较大的大对象
  • 保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者
五、一个结构体实现多个接口
  • GoLang中一个结构体也可以实现多个接口
package main
import "fmt"
type AInterface interface {GetInfo() string
}
type BInterface interface {SetInfo(string, int)
}
type People struct {Name stringAge int
}
func (p People) GetInfo() string {return fmt.Sprintf("姓名:%v 年龄:%d", p.Name, p.Age)
}
func (p *People) SetInfo(name string, age int) {p.Name = namep.Age = age
}
func main() {var people = &People{Name: "Snail",Age: 20,}// people 实现了 AInterface 和 BInterfacevar p1 AInterface = peoplevar p2 BInterface = peoplefmt.Println(p1.GetInfo())p2.SetInfo("pupu", 21)         // 姓名:Snail 年龄:20fmt.Println(p1.GetInfo())      // 姓名:pupu 年龄:21
}
六、接口嵌套(继承)
  • 接口与接口间可以通过嵌套创造出新的接口
package main
import "fmt"
type SayInterface interface {say()
}
type MoveInterface interface {move()
}
// 接口嵌套
type Animal interface {SayInterfaceMoveInterface
}
type Cat struct {name string
}
func (c Cat) say() {fmt.Println("喵喵喵")
}
func (c Cat) move() {fmt.Println("猫会动")
}
func main() {var x Animalx = Cat{name: "花花"}x.move()    // 猫会动x.say()     // 喵喵喵
}

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

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

相关文章

德迅抗D盾是如何防护攻击的

德迅抗D盾是针对游戏行业面对的DDoS、CC攻击推出的针对性的网络安全解决方案,相比高防IP,除了能针对大型DDoS攻击(T级别)进行有效防御外,还具备彻底解决游戏行业特有的TCP协议的CC攻击问题能力,防护成本更低…

基于Java SSM框架实现超市管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现超市管理系统演示 摘要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识&#…

哈希查找(数据结构实训)

题目: 哈希查找 标准输入输出 题目描述: 实现哈希查找。要求根据给定的哈希函数进行存储,并查找相应元素的存储位置。本题目使用的哈希函数为除留取余法,即H(key)key%m,其中m为存储空间,冲突处理方法采用开…

Android的文件切割和合并,补全wav文件头

示例: 1、普通文件的拆分与合并: private void testFile() {File mWavFile new File(getExternalFilesDir(null).getAbsolutePath() "/test.wav");if (!mWavFile.exists()){Log.d("caowj", "文件不存在:" …

多人聊天作业

服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{public static ServerSocket server_socket;public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []args){try{…

如何评估数据资产的价值?哪种方法更容易实现?

今年可以称之为数据年&#xff0c;从去年年底党中央发布《数据20条》&#xff0c;对数据领域的一系列的制度建设做了提纲起领的作用。在财经领域今年的下半年&#xff0c;密集出台一系列跟数据资产相关的政策&#xff0c;包括8月21日发布的《企业数据资源会计处理的暂行规定》以…

最小生成树算法与二分图算法

文章目录 概述 P r i m Prim Prim 算法 - 稠密图 - O ( n 2 ) O(n^2) O(n2)思路概述时间复杂度分析AcWing 858. Prim算法求最小生成树CODE K r u s k a l Kruskal Kruskal 算法 - 稀疏图 - O ( m l o g m ) O(mlogm) O(mlogm)思路解析时间复杂度分析AcWing 859. Kruskal算法求…

后端返回数据前端保留两位小数

一.背景 在平时工作中尤其是银行金融类佘涉及到数据计算问题&#xff0c;数据统计又不能显示太多小数点&#xff0c;很多时候需求不一样&#xff0c;对数据的精度要求也不一样&#xff0c;下面是我在工作中用到的方法总结记录一下。 二.不同需求对应的方法 toFixed() 方法 to…

探索HarmonyOS_开发软件安装

随着华为推出HarmonyOS NEXT 宣布将要全面启用鸿蒙原声应用&#xff0c;不在兼容安卓应用&#xff0c; 现在开始探索鸿蒙原生应用的开发。 HarmonyOS应用开发官网 - 华为HarmonyOS打造全场景新服务 鸿蒙官网 开发软件肯定要从这里下载 第一个为微软系统(windows)&#xff0c;第…

逆向修改Unity的安卓包资源并重新打包

在上一篇文章中,我已经讲过如何逆向获取unity打包出来的源代码和资源了,那么这一节我将介绍如何将解密出来的源代码进行修改并重新压缩到apk中。 其实在很多时候,我们不仅仅想要看Unity的源码,我们还要对他们的客户端源码进行修改和调整,比如替换资源,替换服务器连接地址…

MSSQL注入入门讲解:保护你的数据库免受攻击

MSSQL注入入门讲解&#xff1a;保护你的数据库免受攻击 引言&#xff1a; MSSQL注入是一种常见的网络攻击方式&#xff0c;通过利用应用程序对用户输入的不正确处理&#xff0c;攻击者可以执行恶意代码并获取敏感数据。本篇博客将详细介绍MSSQL注入的原理、常见的攻击技术以及…

【C/C++】函数参数默认值

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

深度学习实战64-黑白照片着色的模型应用,快速部署实现黑白图片快速上色的功能

大家好,我是微学AI,今天给大家介绍一下深度学习实战64-黑白照片着色的模型应用,快速部署实现黑白图片快速上色的功能。图片上色是一个具有多模态不确定性和高度不适定性的挑战性问题。直接训练深度神经网络通常会导致错误的语义颜色和低色彩丰富度。虽然基于Transformer的方…

人工智能AIGC培训讲师叶梓介绍及AI强化学习培训提纲

叶梓&#xff0c;上海交通大学计算机专业博士毕业&#xff0c;高级工程师。主研方向&#xff1a;数据挖掘、机器学习、人工智能。历任国内知名上市IT企业的AI技术总监、资深技术专家&#xff0c;市级行业大数据平台技术负责人。个人主页&#xff1a;大数据人工智能AI培训讲师叶…

9大高效的前端测试工具与框架!

在每个Web应用程序中&#xff0c;作为用户直接可见的应用程序外观&#xff0c;“前端”包括&#xff1a;图形化的用户界面、相应的功能、及其整体站点的可用性。我们可以毫不夸张地说&#xff1a;如果前端无法正常工作&#xff0c;您将无法“拉新”网站的潜在用户。这也正是我们…

Java8新特性CompletableFuture详解

一、概述 CompletableFuture 是Java 8 中引入的 Java Future API的扩展&#xff0c;用于 Java 中的异步编程&#xff0c;它可以使我们的任务运行在与主线程分离的其他线程中&#xff0c;并通过回调在主线程中得到异步任务执行状态&#xff0c;包括是否完成&#xff0c;是否异常…

【Node.js】如何修复“错误:错误:0308010c:digital envelope routines::不受支持”

作为一名开发人员&#xff0c;在项目中遇到错误是很常见的。在这篇博客文章中&#xff0c;我们将讨论一个困扰开发人员的特定错误&#xff0c;尤其是那些使用Node.js的开发人员。有问题的错误是“错误&#xff1a;错误&#xff1a;0308010c:数字信封例程&#xff1a;&#xff1…

MySQL:update set的坑

目录 一、问题描述 二、为何会出现这样的问题&#xff1f; 三、正确的方案 一、问题描述 我在修改mysql数据表时&#xff0c;看到下面的现象。 我表中原始数据如下&#xff1a; 执行了下面的修改&#xff0c;显示执行成功。 update user_function_record_entity set open_…

MySQL_1. mysql数据库介绍

shell脚本差不多快完结了接下来会为大家更新MySQL系列的相关的基础知识笔记&#xff0c;希望对大家有所帮助&#xff0c;好废话不多说&#xff0c;接下来开始正题&#xff01; 1.mysql数据库介绍 mysql 是一款安全、跨平台、高效的&#xff0c;并与 PHP、Java 等主流编程语言…