Golang-interface(一 基本使用)

golang技术随笔(一)深入理解interface Go语言的主要设计者之一罗布·派克( Rob Pike)曾经说过,如果只能选择一个Go语言的特 性移植到其他语言中,他会选择接口。可见接口在golang中的地位,及其对gloang这门语言所带来的活力。      golang中的interface是什么 接口相当于是一份契约,它规定了一个对象所能提供的一组操作。要理解golang中接口的概念我们最好还是先来看看别的现代语言是如何实现 阅读详情

github: https://github.com/ZhangzheBJUT/blog/blob/master/interface.md 

一 接口概述

如果说gorountine和channel是支撑起Go语言的并发模型的基石,让Go语言在如今集群化与多核化的时代成为一道亮丽的风景,那么接口是Go语言整个类型系列的基石,让Go语言在基础编程哲学的探索上达到前所未有的高度。

Go语言在编程哲学上是变革派,而不是改良派。这不是因为Go语言有gorountine和channel,而更重要的是因为Go语言的类型系统,更是因为Go语言的接口。Go语言的编程哲学因为有接口而趋于完美。

C++,Java 使用"侵入式"接口,主要表现在实现类需要明确声明自己实现了某个接口。这种强制性的接口继承方式是面向对象编程思想发展过程中一个遭受相当多质疑的特性。

Go语言采用的是“非侵入式接口",Go语言的接口有其独到之处:只要类型T的公开方法完全满足接口I的要求,就可以把类型T的对象用在需要接口I的地方,所谓类型T的公开方法完全满足接口I的要求,也即是类型T实现了接口I所规定的一组成员。这种做法的学名叫做Structural Typing,有人也把它看作是一种静态的Duck Typing。

Go 是静态类型的。每一个变量有一个静态的类型,也就是说,有一个已知类型并且在编译时就确定下来了

type MyInt int
var i int
var j MyInt

那么 i 的类型为 int 而 j 的类型为 MyInt。即使变量 i 和 j 有相同的底层类型,它们仍然是有不同的静态类型的。未经转换是不能相互赋值的。

二 接口类型

在类型中有一个重要的类别就是接口类型,表达了固定的一个方法集合。一个接口变量可以存储任意实际值(非接口),只要这个值实现了接口的方法。

type Reader interface {
    Read(p []byte) (n int, err os.Error)
}

// Writer 是包裹了基础 Write 方法的接口。
type Writer interface {
    Write(p []byte) (n int, err os.Error)
}

var r io.Reader
r = os.Stdin
r = bufio.NewReader(r)
r = new(bytes.Buffer)

有一个事情是一定要明确的,不论 r 保存了什么值,r 的类型总是 io.Reader,Go 是静态类型,而 r 的静态类型是 io.Reader。

接口类型的一个极端重要的例子是空接口:interface{},它表示空的方法集合,由于任何值都有零个或者多个方法,所以任何值都可以满足它。

也有人说 Go 的接口是动态类型的,不过这是一种误解。 它们是静态类型的:接口类型的变量总是有着相同的静态类型,这个值总是满足空接口,只是存储在接口变量中的值运行时可能被改变。

对于所有这些都必须严谨的对待,因为反射和接口密切相关。

三 接口的特色

接口类型的变量存储了两个内容:赋值给变量实际的值和这个值的类型描述。更准确的说,值是底层实现了接口的实际数据项目,而类型描述了这个项目完整的类型。例如下面,

var r io.Reader
tty, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil { return nil, err }
r = tty

用模式的形式来表达 r 包含了的是 (value, type) 对,如 (tty, *os.File)。 

注意: 类型 *os.File 除了 Read 方法还实现了其他方法:尽管接口值仅仅提供了访问 Read 方法的可能(即通过r 只能访问Read方法),但是内部包含了这个值的完整的类型信息(反射的依据)。

这也就是为什么可以这样做:

var w io.Writer
w = r.(io.Writer) //接口查询

在这个赋值中的断言是一个类型断言:它断言了 r 内部的条目同时也实现了 io.Writer,因此可以赋值它到 w。在赋值之后,w 将会包含 (tty, *os.File),跟在 r 中保存的一致。 

接口的静态类型决定了哪个方法可以通过接口变量调用,即便内部实际的值可能有一个更大的方法集。

接下来,可以这样做:

var empty interface{}
empty = w

而空接口值 e 也将包含同样的 (tty, *os.File)。这很方便:空接口可以保存任何值同时保留关于那个值的所有信息。

注:这里无需类型断言,因为 w 肯定满足空接口的。在上面的个例子中,将一个值从 Reader 变为 Writer,由于 Writer 的方法不是 Reader 的子集,所以就必须明确使用类型断言。

一个很重要的细节是接口内部的对总是 (value, 实际类型) 的格式,而不会有 (value, 接口类型) 的格式。接口不能保存接口值。

四 接口赋值

接口赋值在Go语言中分为两种情况: 1.将对象实例赋值给接口 2.将一个接口赋值给另外一个接口

  • 将对象实例赋值给接口 

    看下面的例子:

      package main
    
      import (
      "fmt"
      )
    
      type LesssAdder interface {
          Less(b Integer) bool
          Add(b Integer)
      }
    
      type Integer int
    
      func (a Integer) Less(b Integer) bool {
          return a < b
      }
    
      func (a *Integer) Add(b Integer) {
          *a += b
      }
    
      func main() {
    
          var a Integer = 1
          var b LesssAdder = &a
          fmt.Println(b)
    
          //var c LesssAdder = a
          //Error:Integer does not implement LesssAdder 
          //(Add method has pointer receiver)
      }
    
    

go语言可以根据下面的函数:

func (a Integer) Less(b Integer) bool 

自动生成一个新的Less()方法

func (a *Integer) Less(b Integer) bool 

这样,类型*Integer就既存在Less()方法,也存在Add()方法,满足LessAdder接口。 而根据

func (a *Integer) Add(b Integer)】

这个函数无法生成以下成员方法:

func(a Integer) Add(b Integer) {
    (&a).Add(b)
}

因为(&a).Add()改变的只是函数参数a,对外部实际要操作的对象并无影响(值传递),这不符合用户的预期。所以Go语言不会自动为其生成该函数。因此类型Integer只存在Less()方法,缺少Add()方法,不满足LessAddr接口。(可以这样去理解:指针类型的对象函数是可读可写的,非指针类型的对象函数是只读的)

  • 将一个接口赋值给另外一个接口 

    在Go语言中,只要两个接口拥有相同的方法列表(次序不同不要紧),那么它们就等同的,可以相互赋值。 如果A接口的方法列表时接口B的方法列表的子集,那么接口B可以赋值给接口A,但是反过来是不行的,无法通过编译。

五 接口查询

接口查询是否成功,要在运行期才能够确定。他不像接口的赋值,编译器只需要通过静态类型检查即可判断赋值是否可行。

var file1  Writer = ...
if file5,ok := file1.(two.IStream);ok {
...
}

这个if语句检查file1接口指向的对象实例是否实现了two.IStream接口,如果实现了,则执行特定的代码。

在Go语言中,你可以询问它指向的对象是否是某个类型,比如,

var file1 Writer = ...
if file6,ok := file1.(*File);ok {
...
}

这个if语句判断file1接口指向的对象实例是否是*File类型,如果是则执行特定的代码。

slice := make([]int, 0)
slice = append(slice, 1, 2, 3)

var I interface{} = slice


if res, ok := I.([]int);ok {
    fmt.Println(res) //[1 2 3]
}

这个if语句判断接口I所指向的对象是否是[]int类型,如果是的话输出切片中的元素。

func Sort(array interface{}, traveser Traveser) error {

    if array == nil {
        return errors.New("nil pointer")
    }
    var length int //数组的长度
    switch array.(type) {
    case []int:
        length = len(array.([]int))
    case []string:
        length = len(array.([]string))
    case []float32:
        length = len(array.([]float32))

    default:
        return errors.New("error type")
    }

    if length == 0 {
        return errors.New("len is zero.")
    }

    traveser(array)

    return nil
}

通过使用.(type)方法可以利用switch来判断接口存储的类型。

小结: 查询接口所指向的对象是否为某个类型的这种用法可以认为是接口查询的一个特例。接口是对一组类型的公共特性的抽象,所以查询接口与查询具体类型区别好比是下面这两句问话的区别:

你是医生么?
是。
你是莫莫莫
是

第一句问话查询的是一个群体,是查询接口;而第二个问句已经到了具体的个体,是查询具体类型。

除此之外利用反射也可以进行类型查询,会在反射中做详细介绍。

参考: http://research.swtch.com/interfaces




Golang笔记——Interface类型 接口定义了类型应该具备的行为(即方法)。Go 的接口与其他语言(如 Java 或 C++)中的接口有一些不同之处,特别是Go 的接口不需要显式声明实现,即只要类型实现了接口的方法,就自动实现了该接口。Method1() // 方法签名Method2() // 方法签名类型断言:用于在运行时提取接口的具体类型值,如果类型不匹配,可以使用ok变量避免运行时错误。类型开关:允许你对接口值的动态类型进行多分支判断,可以在多个可能的类型之间选择。反射:通过reflect包可以。 阅读详情

相关推荐

【GoLang笔记】浅析Go语言Interface类型的语法行为及用法

Go不是一种典型的OO语言,它在语法上不支持类和继承的概念。 没有继承是否就无法拥有多态行为了呢?答案是否定的,Go语言引入了一种新类型—Interface,它在效果上实现了类似于C++的“多态”概念,虽然与C++的多态在语法上并非完全对等,但至少在最终实现的效果上,它有多态的影子。 那么,Go的Interface类型到底是什么呢?怎么使用呢?这正是本篇笔记试图说明的问题。 1. Metho

slvher的专栏 1万+

golang interface to string_Golang | 既是接口又是类型,interface是什么神仙用法?

今天是golang专题的第12篇文章,我们来继续聊聊interface的使用。在上一篇文章当中我们介绍了面向对象的一些基本概念,以及golang当中interface和多态的实现方法。今天我们继续来介绍interface当中其他的一些方法。万能类型interface在Java以及其他语言当中接口是一种写法规范,而在golang当中,interface其实也是一种值,它可以像是值一样传递。并且在它的...

weixin_39739234的博客 531

Go 学习笔记(35)— Go 接口 interface (接口声明、接口初始化、接口方法调用、接口运算、类型断言、类型查询、空接口)

1. 接口概念 接口是双方约定的一种合作协议。接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节。接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式、类型及结构。 接口内部存放的具体类型变量被称为接口指向的“实例”。接口只有声明没有实现,所以定义一个新接口,通常又变成声明一个新接口, 定义接口和声明接口二者通用,代表相同的意思。 最常使用的接口字面量类型就是空接口 interface{} ,由于空接口的方法集为空,所以任意类型都被认为实现了空接口,任意类型的实例都可以赋值或传递给空

wohu1104的专栏 1万+

09Go语言中的接口初始化

接口初始化方式

船长的博客 649

Zynq/ZynqMP PL端以太网实战:手把手教你用GMII to RGMII IP和EMIO打通网络(附KSZ9031 PHY驱动修改)

本文详细介绍了在Zynq/ZynqMP平台上使用GMII to RGMII IP核和EMIO接口实现PL端以太网通信的全栈开发流程,特别针对KSZ9031 PHY芯片提供了定制化驱动修改方案。内容涵盖硬件设计、Vivado配置、裸机驱动开发、Linux系统集成及实战调试技巧,帮助开发者高效解决工业控制和边缘计算中的以太网连接问题。

weixin_30642561的博客 582

AI 模型训练核心方法论:零基础也能落地的 8 个关键阶段

本文是为 AI 零基础学习者打造的模型训练入门指南,以生活化语言拆解核心概念,规避专业术语壁垒。内容先通俗阐释模型训练、监督学习、数据集划分等基础概念,再按问题定义、数据准备、模型选择、环境搭建、训练、评估、调参、部署 8 个阶段,拆解完整训练流程,搭配 PyTorch 代码示例与实战案例,同时提供资源预算、常见问题解决方案及学习路径。指南强调数据的核心重要性,推荐新手优先使用迁移学习和免费 GPU 资源,兼顾理论与实操,帮助学习者快速上手,避开训练误区,独立完成从模型搭建到部署的全流程。

weixin_52741870的博客 469

GoLang之interface

GoLang之interface

weixin_52690231的博客 1764

libfacedetection 框架阅读及扩展经验

libfacedetection 框架源码解析与扩展心得1. libfacedetection 框架简介2. 源码解析2.1 facedetectcnn.h2.2 facedetectcnn.cpp2.3 facedetectcnn-model.cpp3. 其他层的扩展--depthwise convolution 前段时间因为工作需要,对libfacedetection框架做了些扩展,在阅读源...

weixin_42616332的博客 1500

77.Go中interface{}判nil的正确姿势

在go中的nil只能赋值给指针、channel、func、interface、map或slice类型的变量interface是否根据是否包含有method,底层实现上用两种structiface 和 eface。eface:表示不含method的interface结构,或者叫。对于Golang中的大部分数据类型都可以抽象出来_type结构,同时针对不同的类型还会有一些其他信息。iface: 表示的底层实现。相比于non-empty要包含一些method。method的具体实现存放在itab.fun变量里。

YouMing_Li的博客 1765

keil自动分配SDRAM空间设置使用

1.修改.sct文件。

qizhi321123的博客 1404

SAP Script表单开发中ABAP preform方法的实战应用与调试技巧

本文深入探讨了在SAP Script表单开发中调用ABAP程序(preform方法)的实战应用与调试技巧。通过一个获取供应商版本名称的实例,详细讲解了如何在SE71中嵌入PERFORM指令、编写ABAP子程序进行数据查询与处理,并重点介绍了使用SAP Script Debugger进行高效调试的方法,帮助开发者灵活扩展表单功能,实现复杂业务逻辑。

o0p1q2r3的博客 551

Go语言之interface详解

go语言interface详解,interface的使用场景,实现多态示例,

yuqiang870的博客 1万+

【ESP32设备通信】-LoRa通信

在本文中,我们将使用 Arduino IDE 将 ESP32 与 LoRa SX1278 (Ra-02) 模块连接起来。 我们将创建一个真实的示例项目,通过 LoRa 无线打开/关闭 LED 进行演示。

视觉与物联智能 1890

go interface 基本用法

Go 中的接口跟我们常见的编程语言中的接口不太一样,go 里面实现接口是不需要使用implements关键字显式声明的,go 的接口为我们提供了难以置信的一系列的灵活性和抽象性。接口本质是一种自定义类型。(跟 Java 中的接口不一样)接口是一种特殊的自定义类型,其中没有数据成员,只有方法(也可以为空)。接口是完全抽象的,不能将其实例化。然后,对于接口类型变量,我们可以把任何实现了接口所有方法的类型变量赋值给它,这个过程不需要显式声明。例如,假如Bird实现了Fly。

rubys_的专栏 1478

构建高效的LLM应用测试框架

《构建高效的LLM应用测试框架》 关键词:LLM,测试框架,应用测试,效率优化,测试原理 摘要:本文将深入探讨构建高效LLM应用测试框架的必要性、方法与步骤,旨在为开发者提供一套系统化、可操作的测试解决方案,从而提升LLM

AI天才研究院 1048

linux系统宝塔服务器temp文件夹里总是被上传病毒php脚本

服务器时不时的会发送短信说你服务器有病毒,找到了这个tmp文件,删除了之后又有了。确实是有很多人就这么无聊,每天都攻击你的服务器。找了很久的原因,网上也提供了一大堆方法,但都是很简陋的答案,具体怎么操作并没有说。没办法只能自己去排查这个问题。从两个角度来考虑,第一是服务器系统问题,比如宝塔的漏洞。但一时半会看不出问题来。只能去排查自己的项目代码。最后了解到代码确实是存在漏洞的。但代码中也确实了很多的校验,为什么会存在漏洞了?这就不得不从上传的过程开始说起。

guiplan 1497

go interface 设计与实现

在了解 gointerface的设计过程中,看了不少资料,但是大多数资料都有生成汇编的操作,但是在我的电脑上指向生成汇编的操作的时候,生成的汇编代码却不太一样,所以有很多的东西无法验证正确性,这部分内容不会出现在本文中。本文只写那些经过本机验证正确的内容,但也不用担心,因为涵盖了 gointerface设计与实现的核心部分内容,但由于水平有限,所以只能尽可能地传达我所知道的关于interface的一切东西。对于有疑问的部分,有兴趣的读者可以自行探索。如果想详细地了解,建议还是去看看iface.go。

rubys_的专栏 1590

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

理解Golang中的[]interface{}和interface{}

理解Golang中的[]interface{}和interface{} 之前在开发Go项目操作Redis时,利用Do函数进行数据操作,在返回的interface{}类型的转换中踩了一个大坑。 Do(ctx, "HKEYS", "KEY") 在阅读源码中发现,Do方法的是一个[]interface{}切片 func (c *Redis) Do(ctx context.Context, commandName string, args ...interface{}) (interface{}, error)

qq_39220627的博客 7724

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Go-学会 Go 中 interface 的基本使用

在 Go 中,接口类型是一种抽象类型,是方法的集合,其他类型实现了这些方法就是实现了这个接口。

IT小猿 1113

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Go interface详解

Interface 使用场景依赖注入是一种设计模式,它可以减少类之间的耦合,提高代码的可维护性和可测试性。依赖注入的基本思想是,不让类自己创建它所依赖的对象,而是通过外部的方式(如构造函数、参数、属性等)将依赖的对象传递(或注入)给类。这样,类就不需要知道依赖对象的具体实现,只需要调用它们的接口方法。依赖注入有以下好处:

qq_29647593的博客 2704

go interface

go语言里,interface的地位举足轻重,可谓是go语言的灵魂。下面通过两个例子说明interface的使用。 示例一 package main import ( "fmt" "strconv" ) type sdxp struct{ index int name string } type idriver interface{ driver1()string driv...

好记性不如写博客! 1555

Golang interface{}

是 Go 中可以表示任意类型的“空接口”,是实现泛型编程的基础工具之一。

gopher123的博客 1193
上一篇: 为什么要使用NoSQL
下一篇: Golang-interface(二 接口与nil)
张哲BJUT
博客等级 码龄15年 151粉丝 111原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值