Go 接口
接口概览
| 接口大概理解 | 接口类型是队其他类型行为的概括与抽象 |
| 接口类型中,包含函数声明,但没有数据变量 | |
| 接口的作用 | 通过使用接口,可以写出更加灵活和通用的函数,这些函数不用绑定在一个特定的类型实现上 |
| Go 接口特征 | 很多面向对象的语言都有接口这个概念,Go 语言的接口的独特之处在于,Go 接口是 "隐式实现" 也就是说,对于一个具体的类型 T ,无须声明类型 T 实现了哪些接口,只要提供接口所必需的方法即可 解释 :没有具体的语法,显式地表明一个具体类实现(继承)了某个接口;只要这个具体类实现(重写)了某个接口中的函数,那么这个具体类就是实现了该接口 这种接口的 "隐式实现" ,可以无须改变具体类的实现,就可以为具体类创建新的接口(功能),对于那些不能修改包的类型,这一点特别有用 |
什么是接口
| 具体类型 | (i). 之前介绍的都是具体类型 (ii). 具体类型指定了所含数据的精确布局,还暴露了基于数据精确布局的内部操作 比如数值有算术操作,对于 slice 类型有索引 、append 、range 等操作 (iii). 具体类型还能通过新增方法来提供额外的能力 总之,如果知道了一个具体类型的数据,就精确地知道了该类型是什么以及能干什么 |
| 接口 | Go 语言中,还有另外一种类型称为 "接口类型" (i). "接口" 是一种 "抽象类型" (ii). 接口没有暴露所含数据的布局或者内部结构,也没有对于数据的操作,接口所提供的只是一些方法 (iii). 如果得到一个接口类型的值,则无法知道它是什么,只知道该接口值能做什么 说的直白一点,接口就是只包含函数声明的类,而且没有成员数据 |
| 示例 | 下面使用两个类似的函数,实现字符串的格式化 :fmt.Printf 和 fmt.Sprintf fmt.Printf 把结果发送到标准输出(标准输出其实就是一个文件) fmt.Sprintf 把结果以 string 类型返回 格式化是这两个函数中最复杂的部分,如果仅仅因为两个函数在输出方式上的轻微差异,就需要把格式化部分在。两个函数中重复实现一遍,那就太糟糕了; 幸运的是,通过接口机制可以解决这个问题; 其实,两个函数都封装了第三个函数 fmt.Fprintf ,而这个函数对结果实际输出到哪里毫不关心 : package fmt func Fprintf( w io.Writer,format string,args ...interface{} ) ( int,error ) func Printf( format string,args ...interface{} ) ( int,error ) { return Fprintf(os.Stdout ,format ,args...) } func Sprintf( format string,args ...interface{} ) string { var buf bytes.Buffer Fprintf(&buf ,format ,args...) return buf.String() } |
| 说明 | (i). Fprintf 的前缀 F 指文件,表示格式化的输出会写入第一个实参所指代的文件 (ii). 对于 Printf ,第一个实参就是 os.Stdout ,它属于 *os.File 类型 (iii). 对于 Sprintf ,尽管第一个实参不是文件,但第一个实参模拟了一个文件 : &buf 就是一个指向内存缓冲区的指针,与文件类似,该缓冲区可以写入多个字节 (iv). 其实,Fprintf 的第一个形参也不是文件类型,而是 io.Writer 接口类型,其声明如下: package io // Writer 接口封装了基础的写入方法 type Writer interface { // Write 从 p 向底层数据流写入 len(p) 个字节的数据 // 返回实际写入的字节数 ( 0 <= n <= len(p) ) // 如果没有写完,那么会返回遇到的错误 // 在 Write 返回 n < len(p) 时,err 必须为非 nil // Write 不允许修改 p 的数据,即使是临时修改 // // 实现时不允许残留 p 的引用 Write( p []byte ) ( n int ,err error ) } io.Writer 接口定义了 Fprintf 和调用者之间的约定: 在使用函数 Fprintf 时,给到的第一个实参类型应该实现了接口 io.Writer 一方面,这个约定,要求调用者提供的具体类型(比如 *os.File 或 *bytes.Buffer)包含一个与其(接口中的方法签名)签名和行为一致的 Write 方法 签名一致,就是说,具体类型中,也有一个如下的,完全一样的方法 Write(p []byte) (n int , err error ) 行为一致,就是说,Write 从 p 向底层数据流写入 len(p) 个字节的数据,这里的底层数据流是数据的终点,这个终点相当于具体类型的一个成员;也就是说,方法 Write 会把数据写入具体类型中,而这个数据来源就是格式化字符串 另一方面,这个约定保证了 Fprintf 能使用任何满足 io.Writer 接口的参数; Fprintf 只需要能调用参数(具体类型)的 Write 函数,无须假设 Write 写入的是一个文件还是一段内存(只要能写入数据即可) 因为 fmt.Fprintf 仅依赖于 io.Writer 接口所约定的方法,对参数的具体类型没有要求,所以我们可以用任何满足(实现)io.Writer 接口的具体类型作为 fmt.Fprintf 的第一个实参 这种可以把一种类型替换为满足同一接口的另一种类型的特性,称为 "可取代性" ,这也是面向对象语言的典型特征 |
| 代码测试 | 创建一个新类型来测试一下这个特性。如下所示的 *ByteCounter 类型的 Write 方法仅仅统计传入数据的字节数,然后就不管那些数据了 (下面的代码中出现的类型转换是为了让 len(p) 和 *c 满足 += 操作) type ByteCounter int func (c *ByteCounter) Write(p []byte) (int,error) { *c += ByteCounter(len(p)) // 转换 int 为 ByteCounter 类型 return len(p) ,nil } 因为 *ByteCounter 满足 io.Writer 接口的约定,所以能在 Fprintf 中使用 ByteCounter ,Fprintf 察觉不到这种类型差异,ByteCounter 也能正确地累积格式化后结果的长度 var c ByteCounter c.Write([]byte("hello")) fmt.Println(c) // "5",= len("hello") c = 0 // 重置计数器 var name = "Dolly" fmt.Fprintf(&c,"hello,%s",name) fmt.Println(c) // "12",= len("hello,Dolly") |
| 除了 io.Writer 之外,fmt 包还有一个重要的接口 Fprintf 和 Fprintln 提供了一个让类型控制如何输出自己的机制 给 Celsius 类型定义了一个 String 方法,这样可以输出 "100℃" 这样的结果; 给 *IntSet 类型加了一个 String 方法,这样可以输出类似 "{1 2 3}" 的传统集合表示形式 定义一个 String 方法就可以让类型满足这个广泛使用的接口 fmt.Stringer : package fmt // 在字符串格式化时如果需要一个字符串 // 那么就调用这个方法来把当前值转换为字符串 // Print 这种不带格式化参数的输出方式也是调用这个方法 type Stringer interface { String() string } |
接口类型(声明)
接口是隐式实现 :
一个接口类型定义了一套方法,如果一个具体类型要实现该接口,那么必须实现接口类型定义中的所有方法
声明接口的几种方式
前提说明:
io.Writer 是一个广泛使用的接口,负责所有可以写入字节的类型的抽象,包括文件 、内存缓冲区 、网络连接 、HTTP 客户端 、打包器(archiver)、散列器(hasher)等;
io 包还定义了很多有用的接口;
Reader 就抽象了所有可以读取字节的类型,Closer 抽象了所有可以关闭的类型,比如文件或者网络连接
注意 :Go 语言的单方法接口的命名约定
说明 :字节流的最终目的地,位于具体类型中,接口是具体类型的抽象或者说概括
基础接口声明
package io
type Reader interface {Read(p []byte) (n int, err error)
}type Closer interface {Close() error
}
方式一(组合接口)
可以通过组合已有接口得到新接口;
下面这种声明接口的方式,称为 "嵌入式接口"
与嵌入式结构类似,可以直接使用一个接口,而不用逐一写出这个接口包含的方法
type ReadWriter interface {ReaderWriter
}type ReadWriteCloser interface {ReaderWriterCloser
}
方式二(组合方法)
尽管不够简洁,但是可以不用嵌入式来声明 io.ReadWriter
type ReadWriter interface {Read(p []byte) (n int, err error)Write(p []byte) (n int, err error)
}
方式三(组合接口、方法)
可以混合使用两种方式
type ReadWriter interface {Read(p []byte) (n int, err error)Writer
}
总结:
三种声明的效果都是一样的;
方法定义的顺序也是没有影响的,真正有意义的只有接口的方法集合
| 隐式实现 | 一个接口类型定义了一套方法,如果一个具体类型要实现该接口,那么必须实现接口类型定义中的所有方法 |
| 声明接口的几种方式 | |
| 前提说明 | io.Writer 是一个广泛使用的接口,负责所有可以写入字节的类型的抽象,包括文件 、内存缓冲区 、网络连接 、HTTP 客户端 、打包器(archiver)、散列器(hasher)等; io 包还定义了很多有用的接口; Reader 就抽象了所有可以读取字节的类型,Closer 抽象了所有可以关闭的类型,比如文件或者网络连接 注意 :Go 语言的单方法接口的命名约定 说明 :字节流的最终目的地,位于具体类型中,接口是具体类型的抽象或者说概括 |
| 基础接口声明 | package io type Reader interface { Read(p []byte) ( n int ,err error ) } type Closer interface { Close() error } |
| 方式一 (组合接口) | 另外,还可以通过组合已有接口得到新接口 type ReadWriter interface { Reader Writer } type ReadWriteCloser interface { Reader Writer Closer } 上面这种声明接口的方式,称为 "嵌入式接口" 与嵌入式结构类似,可以直接使用一个接口,而不用逐一写出这个接口包含的方法 |
| 方式二 (组合方法) | 如下所示,尽管不够简洁,但是可以不用嵌入式来声明 io.ReadWriter type ReadWriter interface { Read(p [ ]byte) ( n int ,err error ) Write(p [ ]byte) (n int ,err error) } |
| 方式三 (组合接口、方法) | 也可以混合使用两种方式 type ReadWriter interface { Read(p [ ]byte) ( n int ,err error ) Writer } |
| 三种声明的效果都是一样的; 方法定义的顺序也是没有影响的,真正有意义的只有接口的方法集合 | |
接口实现
示例:使用 flag.Value 来解析参数
相关文章:
Go 接口
接口概览 接口大概理解 接口类型是队其他类型行为的概括与抽象 接口类型中,包含函数声明,但没有数据变量接口的作用通过使用接口,可以写出更加灵活和通用的函数,这些函数不用绑定在一个特定的类型实现上Go 接口特征 很多面向对象…...
用 AI 将自拍照 P 进不同艺术作品,谷歌发布「艺术自拍 2」
1 月 24 日消息,谷歌旗下「艺术与文化」应用今日宣布,2018 年推出的「艺术自拍」功能在时隔近六年后,借助生成式 AI 的力量回归。官方表示,「艺术自拍 2」将再次使用户与艺术面对面,重新探访世界各地的艺术、历史和文化…...
SpringSecurity+OAuth2.0 搭建认证中心和资源服务中心
目录 1. OAuth2.0 简介 2. 代码搭建 2.1 认证中心(8080端口) 2.2 资源服务中心(8081端口) 3. 测试结果 1. OAuth2.0 简介 OAuth 2.0(开放授权 2.0)是一个开放标准,用于授权第三方应用程序…...
c# 策略模式
在 C# 中,策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装到具有公共接口的独立类中,使得它们可以互相替换。这样可以使得算法的选择独立于算法的使用者,从而提高了灵活性和可维护性。 以下是策略…...
消息队列RabbitMQ.03.死信交换机的讲解与使用
目录 一、死信队列(延迟队列) 概念讲解 二、确认消息(局部方法处理消息) 三、代码实战 1.编写生产者代码,配置消息、直连交换机、路由键 1.1代码解析: 2.配置消费者接受类接受直连交换机的路由键 2.1. String msgÿ…...
人工智能原理实验4(2)——贝叶斯、决策求解汽车评估数据集
🧡🧡实验内容🧡🧡 汽车数据集 车子具有 buying,maint,doors,persons,lug_boot and safety六种属性,而车子的好坏分为uncc,ucc,good and vgood四种。 🧡🧡贝叶斯求解🧡🧡…...
算力网络:未来计算资源的驱动力
文章目录 前言一、算力网络的基本概况(一)算力网络的基本概念(二)算力网络研究进展二、运营商的算力网络架构(一)算力网络基础设施构成(二)算力网络编排管理(三)能力开放三、算力网络的优势(一)弹性计算(二)降低成本(三)去中心化四、算力网络的应用场景(一)人…...
java动态导入excel按照表头生成数据库表
1、创建接口接收文件 //controller层 PostMapping("/importExcel1")public void importExcel1(HttpServletRequest request, MultipartFile file) {try {waterMeterService.importExcel1(request,file);} catch (Exception e) {throw new RuntimeException(e);}}//se…...
Java 集合List相关面试题
📕作者简介: 过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📗本文收录于java面试题系列,大家有兴趣的可以看一看 📘相关专栏Rust初阶教程、go语言基…...
k8s-基础知识(Pod,Deployment,ReplicaSet)
k8s职责 自动化容器部署和复制随时扩展或收缩容器容器分组group,并且提供容器间的负载均衡实时监控,即时故障发现,自动替换 k8s概念及架构 pod pod是容器的容器,可以包含多个container pod是k8s最小可部署单元,容器…...
matlab查看源代码
matlab函数源代码-查看 CtrlD 最简单方便的一种方法,鼠标划中函数名,按CTRLD即可打开函数的m文件...
【数据库学习】PostgreSQL优化
1,思路 2,执行计划 explain sql语句; #查看执行计划。也可以使用navicat的解释功能查看。结果说明: QUERY PLAN Index Scan using tenk1_unique1 on tenk1 (cost0.00..10.01 rows1 width244) --Index 使用索引 --cost&#x…...
微信小程序分页加载功能,结合后端实现上拉底部加载下一页数据,数据加载中和暂无数据提示
🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回&#…...
idea 打包跳过测试
IDEA操作 点击蓝色的小球 手动命令 mvn clean package -Dmaven.test.skiptrue...
python sqlite3 线程池封装
1. 封装 sqlite3 1.1. 依赖包引入 # -*- coding: utf-8 -*- #import os import sys import datetime import loggingimport sqlite31.2. 封装类 class SqliteTool(object):#def __init__(self, host, port, user, password, database):def __init__(self, host, database):s…...
亚马逊运营:如何通过自养号测评有效防关联,避免砍单
店铺安全对于跨境电商卖家至关重要,它是我们业务稳定运营的基础。一旦店铺遭到亚马逊的封禁,往往意味着巨大的损失。因此,合规运营已经成为了卖家们的共识。然而,许多卖家可能会因为一些看似微小的失误,导致店铺被关联…...
winfrom图像加速渲染时图像不显示
winform中加入这段代码,即使不调用也会起作用;当图像不显示时,可以注释掉这段代码...
Redash 默认key漏洞(CVE-2021-41192)复现
Redash是以色列Redash公司的一套数据整合分析解决方案。该产品支持数据整合、数据可视化、查询编辑和数据共享等。 Redash 10.0.0及之前版本存在安全漏洞,攻击者可利用该漏洞来使用已知的默认值伪造会话。 1.漏洞级别 中危 2.漏洞搜索 fofa "redash"…...
Git学习笔记:3 git tag命令
文章目录 git tag 基本用法1. 创建标签2. 查看标签3. 删除标签4. 推送标签到远程仓库5. 检出标签 普通提交和标签的区别1. 提交(Commit)2. 标签(Tag) git tag 基本用法 git tag 是 Git 中用于管理和操作标签(tag&…...
10年软件测试经验,该有什么新的职业规划?
个人觉得,最关键是识别个人的兴趣和长期目标,以及市场需求,制定符合自己职业发展的规划,列了几个常见的方向: 1. 技术深化 专业领域专长:在某一测试领域(如自动化测试、性能测试、安全测试等&am…...
STM32F103C8T6接KY-9250陀螺仪,串口数据解析与姿态角计算全流程(附避坑点)
STM32F103C8T6与KY-9250陀螺仪实战:从硬件对接到姿态解算的完整指南 第一次拿到STM32开发板和KY-9250模块时,那种既兴奋又忐忑的心情记忆犹新——兴奋于即将实现酷炫的姿态检测功能,忐忑于不知从何下手的迷茫。本文将以手把手的方式ÿ…...
告别Salesforce!这5个开源AI CRM项目,帮你用更低成本打造专属客户管理系统
开源AI CRM革命:5个低成本替代方案深度评测与技术选型指南 当Salesforce的年费账单突破六位数时,越来越多的技术决策者开始将目光转向开源生态。这不是简单的成本妥协,而是一场关于数据主权、技术栈控制和AI原生体验的范式转移。以下是经过三…...
Wnt/β-catenin信号通路在组织修复与再生中的关键作用
1. Wnt/β-catenin信号通路:细胞修复的"总指挥" 想象一下你手指被划伤后伤口愈合的过程,或者肝脏在受损后自我修复的神奇能力。这些看似平常的现象背后,其实隐藏着一个精密的分子调控网络——Wnt/β-catenin信号通路。这条通路就像…...
Qwen-Image-Edit-2509镜像部署实战:跟着图文教程,10分钟跑通AI修图
Qwen-Image-Edit-2509镜像部署实战:跟着图文教程,10分钟跑通AI修图 1. 快速了解Qwen-Image-Edit-2509 Qwen-Image-Edit-2509是阿里巴巴通义千问团队推出的最新AI图像编辑工具。这个模型最大的特点是能够理解自然语言指令,对图片进行智能修改…...
从Blender到虚幻引擎:除了FBX,试试GLTF格式导入的完整流程与优势对比
从Blender到虚幻引擎:GLTF格式导入的完整流程与优势解析 在三维内容创作领域,Blender与虚幻引擎的组合已经成为许多专业团队的标准工具链。当我们需要将精心制作的模型从Blender迁移到虚幻引擎时,传统的FBX格式虽然广为人知,但GLT…...
大数据在电力行业的应用案例解析 -【电力技术】(一)—— 基于电力大客户运营的大数据落地拓展
目录 一、电力大客户运营场景与大数据价值 二、大数据平台架构(大客户运营专用) 三、落地应用案例一:电力大客户价值分群与精准画像 1. 业务目标 2. 数据宽表(工程常用) 3. 核心算法:K-Means 用户分群(简化示例代码) 4. 应用效果 四、落地应用案例二:大客户负荷…...
风扇智能调节终极指南:三步打造安静高效的散热系统
风扇智能调节终极指南:三步打造安静高效的散热系统 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/Fa…...
BY8X01-16P Arduino音频模块驱动库深度解析
1. 项目概述BY8X01-16P-Arduino 是一款专为 Arduino 生态设计的轻量级、高兼容性音频模块控制库,面向 BY8001-16P 与 BY8301-16P(文档中偶见笔误为 BY83001-16P)双芯片平台。该库并非简单封装串口指令,而是以嵌入式系统工程视角重…...
手把手教你用ROS2和ZED2 SDK搭建3D视觉开发环境(Ubuntu 20.04版)
手把手教你用ROS2和ZED2 SDK搭建3D视觉开发环境(Ubuntu 20.04版) 在自动驾驶、增强现实和机器人导航等领域,3D视觉感知已成为核心技术之一。ZED2相机凭借其双目深度感知能力和高精度SLAM算法,成为开发者构建空间智能系统的首选传感…...
OWASP靶场实战指南:从环境搭建到第一个SQL注入漏洞挖掘(含DVWA通关思路)
OWASP靶场实战指南:从环境搭建到第一个SQL注入漏洞挖掘 网络安全的世界就像一片未知的海洋,而靶场就是我们练习游泳的安全泳池。对于刚入门的新手来说,最大的困扰往往不是缺乏理论知识,而是不知道如何将所学付诸实践。OWASP靶场正…...
