我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Go接口怎么用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Go接口怎么用

这篇文章给大家分享的是有关Go接口怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

接口是一种抽象类型,是对其他类型行为的概括与抽象,从语法角度来看,接口是一组方法定义的集合。很多面向对象的语言都有接口这个概念,但Go语言接口的独特之处在于它是隐式实现。

Go接口怎么用

1.接口

在Go中使用interface关键字声明一个接口:

type Shaper interface {Area() float64Perimeter() float64}

如果我们直接使用fmt库进行输出,会得到什么结果呢?

func main() {var s Shaperfmt.Println("value of s is ", s)fmt.Printf("type of s is %T\n", s)}

输出:

value of s is  type of s is

在这里,引出接口的概念。接口有两种类型。接口的静态类型是接口本身,例如上述程序中的Shape。接口没有静态值,而是指向动态值。

接口类型的变量可以保存实现接口的类型的值。该类型的值成为接口的动态值,并且该类型成为接口的动态类型。

从上面的示例开始,我们可以看到零值和接口的类型为nil。这是因为,此刻,我们已声明类型Shaper的变量s,但未分配任何值。当我们使用带有接口参数的fmt包中的Println函数时,它指向接口的动态值,Printf功能中的%T语法是指动态类型的接口。实际上,接口静态类型是Shaper。

当我们使用一个类型去实现该接口后,会是什么效果。

type Rect struct {width  float64height float64}func (r Rect) Area() float64 {return r.width * r.height}func (r Rect) Perimeter() float64 {return 2 * (r.width + r.height)}// mainfunc main() {var s Shaperfmt.Println("value of s is ", s)fmt.Printf("type of s is %T\n", s)s = Rect{5.0, 4.0}r := Rect{5.0, 4.0}fmt.Printf("type of s is %T\n", s)fmt.Printf("value of s is %v\n", s)fmt.Printf("area of rect is %v\n", s.Area())fmt.Println("s == r is", s == r)}

输出:

value of s is  type of s is  type of s is main.Rectvalue of s is {5 4}area of rect is 20s == r is tru

可以看到此时s变成了动态类型,存储的是main.Rect,值变成了{5,4}。

有时,动态类型的接口也称为具体类型,因为当我们访问接口类型时,它会返回其底层动态值的类型,并且其静态类型保持隐藏。

我们可以在s上调用Area方法,因为接口Shaper定义了Area方法,而s的具体类型是Rect,它实现了Area方法。该方法将在接口保存的动态值上被调用。

此外,我们可以看到我们可以使用s与r进行比较,因为这两个变量都保存相同的动态类型(Rect类型的结构)和动态值{5 4}。

我们接着使用圆来实现该接口:

type Circle struct {radius float64}func (c Circle) Area() float64 {return 3.14 * c.radius * c.radius}func (c Circle) Perimeter() float64 {return 2 * 3.14 * c.radius}// mains = Circle{10}fmt.Printf("type of s is %T\n", s)fmt.Printf("value of s is %v\n", s)fmt.Printf("area of rect is %v\n", s.Area())

此时输出:

type of s is main.Circlevalue of s is {10}area of rect is 314

这里进一步理解了接口保存的动态类型。从切片角度出发,可以说,接口也以类似的方式工作,即动态保存对底层类型的引用。

当我们删除掉Perimeter的实现,可以看到如下报错结果。

./rect.go:34:4: cannot use Rect{...} (type Rect) as type Shaper in assignment:Rect does not implement Shaper (missing Perimeter method)

从上面的错误应该是显而易见的,为了成功实现接口,需要实现与完全签名的接口声明的所有方法。

2.空接口

当一个接口没有任何方法时,它被称为空接口。这由接口{}表示。因为空接口没有方法,所以所有类型都隐式地实现了这个接口。

空接口的作用之一在于:函数可以接收多个不同类型参数。

例如:fmt的Println函数。

func Println(a ...interface{}) (n int, err error)Println是一个可变函数,它接受interface{}类型的参数。

例如:

type MyString stringfunc explain(i interface{}) {fmt.Printf("type: %T, value: %v\n", i, i)}// mains := MyString("hello")explain(s)r := Rect{1, 2}explain(r)

输出:

type: inter.MyString, value: hellotype: inter.Rect, value: {1 2}

可以看到空接口的类型与值是动态的。

3.多个接口

在下面的程序中,我们用Area方法创建了Shape接口,用Volume方法创建了Object接口。因为结构类型Cube实现了这两个方法,所以它实现了这两个接口。因此,我们可以将结构类型Cube的值赋给类型为Shape或Object的变量。

type IShape interface {Area() float64}type Object interface {Volume() float64}type Cube struct {side float64}func (c Cube) Area() float64 {return 6 * c.side * c.side}func (c Cube) Volume() float64 {return c.side * c.side * c.side}// mainc := Cube{3}var s IShape = cvar o Object = cfmt.Println("area is", s.Area())fmt.Println("Volume is", o.Volume())

这种调用是没有问题的,调用各自动态类型的方法。

那如果是这样呢?

fmt.Println("area of s of interface type IShape is", s.Volume())fmt.Println("volume of o of interface type Object is", o.Area())

输出:

s.Volume undefined (type Shape has no field or method Volume)o.Area undefined (type Object has no field or method Area)

这个程序无法编译,因为s的静态类型是IShape,而o的静态类型是Object。因为IShape没有定义Volume方法,Object也没有定义Area方法,所以我们得到了上面的错误。

要使其工作,我们需要以某种方式提取这些接口的动态值,这是一个立方体类型的结构体,立方体实现了这些方法。这可以使用类型断言来完成。

4.类型断言

我们可以通过i.(Type)确定接口i的底层动态值,Go将检查i的动态类型是否与type相同,并返回可能的动态值。

var s1 IShape = Cube{3}c1 := s1.(Cube)fmt.Println("area of s of interface type IShape is", c1.Volume())fmt.Println("volume of o of interface type Object is", c1.Area())

这样便可以正常工作了。

如果IShape没有存储Cube类型,且Cube没有实现IShape,那么报错:

impossible type assertion:Cube does not implement IShape (missing Area method)

如果IShape没有存储Cube类型,且Cube实现Shape,那么报错:

panic: interface conversion: inter.IShape is nil, not inter.Cub

幸运的是,语法中还有另一个返回值:

value, ok := i.(Type)

在上面的语法中,如果i有具体的type类型或type的动态值,我们可以使用ok变量来检查。如果不是,那么ok将为假,value将为Type的零值(nil)。

此外,使用类型断言可以检查该接口的动态类型是否实现了其他接口,就像前面的IShape的动态类型是Cube,它实现了IShape、Object接口,如下例子:

vaule1, ok1 := s1.(Object)value2, ok2 := s1.(Skin)fmt.Printf("IShape s的动态类型值是: %v, 该动态类型是否实现了Object接口: %v\n", vaule1, ok1)fmt.Printf("IShape s的动态类型值是: %v, 该动态类型是否实现了Skin接口: %v\n", value2, ok2)

输出:

IShape s的动态类型值是: {3}, 该动态类型是否实现了Object接口: trueIShape s的动态类型值是: , 该动态类型是否实现了Skin接口: false

类型断言不仅用于检查接口是否具有某个给定类型的具体值,而且还用于将接口类型的给定变量转换为不同的接口类型。

5.类型Switch

在前面的空接口中,我们知道将一个空接口作为函数参数,那么该函数可以接受任意类型,那如果我有一个需求是:当传递的数据类型是字符串时,要求全部变为大写,其他类型不进行操作?

针对这样的需求,我们可以采用Type Switch,即:i.(type)+switch。

func switchProcess(i interface{}) {switch i.(type) {case string: fmt.Println("process string")case int: fmt.Println("process int")default: fmt.Printf("type is %T\n", i)}}

输出:

process intprocess string

6.嵌入接口

在Go中,一个接口不能实现或扩展其他接口,但我们可以通过合并两个或多个接口来创建一个新的接口。

例如:

这里使用Runner与Eater两个接口,组合成了一个新接口RunEater,该接口为Embedding interfaces。

type Runner interface {run() string}type Eater interface {eat() string}type RunEater interface {RunnerEater}type Dog struct {age int}func (d Dog) run() string {return "run"}func (d Dog) eat() string {return "eat"}// maind := Dog{10}var re RunEater = dvar r Runner = dvar e Eater = dfmt.Printf("RunnEater dynamic type: %T, value: %v\n", re, re)fmt.Printf("Runn dynamic type: %T, value: %v\n", r, r)fmt.Printf("Eater dynamic type: %T, value: %v\n", e, e)

输出:

RunnEater dynamic type: inter.Dog, value: {10}Runn dynamic type: inter.Dog, value: {10}Eater dynamic type: inter.Dog, value: {10}

7.接口比较

如果基础动态值为nil,则两个接口总是相等的,这意味着两个nil接口总是相等的,因此== operation返回true。

var a, b interface{}fmt.Println( a == b ) // true

如果这些接口不是nil,那么它们的动态类型(具体值的类型)应该相同,具体值应该相等。

如果接口的动态类型不具有可比性,例如slice、map、function,或者接口的具体值是包含这些不可比较性值的复杂数据结构,如切片或数组,则==或!=操作将导致运行时panic。

感谢各位的阅读!关于“Go接口怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Go接口怎么用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Go接口怎么用

这篇文章给大家分享的是有关Go接口怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。接口是一种抽象类型,是对其他类型行为的概括与抽象,从语法角度来看,接口是一组方法定义的集合。很多面向对象的语言都有接口这个概念
2023-06-27

Go接口怎么使用

本篇内容主要讲解“Go接口怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go接口怎么使用”吧!接口用法简介接口(interface)是一种类型,用来定义行为(方法)。type Namer
2023-06-30

go怎么声明空接口

在Go语言中,可以使用`interface{}`来声明空接口。下面是一个示例代码:package mainimport "fmt"func main() {var emptyInterface interface{}emptyInterf
2023-10-25

Go语言中的接口怎么使用

今天小编给大家分享一下Go语言中的接口怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。接口在 Go 语言中,接口是一种
2023-07-04

Go语言中io包核心接口怎么用

小编给大家分享一下Go语言中io包核心接口怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Readerio.Reader接口定义了 Read 方法,用于读取数
2023-06-22

Go语言接口类型怎么定义

今天小编给大家分享一下Go语言接口类型怎么定义的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。接口接口是用来定义行为的类型,定
2023-07-05

java接口怎么用

这篇文章主要介绍了java接口怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。接口功能介绍1、‘纯’抽象类的实现(参见JAVA编程思想P/153)// Interface
2023-06-03

C#接口怎么用

小编给大家分享一下C#接口怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!C#接口实例应用问题的提出,假设我们公司有两种程序员:VB程序员,指的是用VB写程序的程序员,用clsVBProgramer这个类表示;Delp
2023-06-17

WCF接口怎么用

这篇文章主要为大家展示了“WCF接口怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“WCF接口怎么用”这篇文章吧。WCF提供了四种类型的行为:服务行为、终结点行为、契约行为和操作行为。这四种
2023-06-17

Go 中烧脑的接口及空接口

文章介绍了Go中的接口和空接口。接口允许定义方法以表示类型,促进解耦、多态性和依赖注入。空接口则不定义任何方法,可以存储任何类型的值,提供通用性和类型断言。文章强调了接口和空接口的区别,并建议优先使用普通接口以确保类型安全。
Go 中烧脑的接口及空接口
2024-04-02

Go之接口型函数用法

这篇文章主要介绍了Go之接口型函数用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-02-10

Go语言函数、结构体、方法和接口怎么用

本篇内容介绍了“Go语言函数、结构体、方法和接口怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 函数Go语言的函数属于“一等公民”
2023-06-30

go语言接口是干什么

go语言接口提供了一种灵活的方式来定义对象的行为,并且可以在不关心具体实现的情况下使用这些对象。通常用于:1、抽象数据类型,可以定义一个抽象的数据类型,该类型可以由不同的具体类型实现;2、依赖注入,可以将一个对象的实现与其使用分离;3、测试
go语言接口是干什么
2023-12-11

GO语言中接口和接口型函数如何使用

这篇文章主要讲解了“GO语言中接口和接口型函数如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“GO语言中接口和接口型函数如何使用”吧!// A Getter loads data fo
2023-07-05

java.sql.ResultSetMetaData接口怎么使用

Java.sql.ResultSetMetaData接口ResultSetMetaData接口提供有关ResultSet对象中列的元数据信息,包括列名、数据类型、大小和可空性。使用此接口,开发人员可以在JDBC中获取数据库元数据,从而了解从数据库检索的数据详细信息,有利于动态查询、错误处理和性能优化。
java.sql.ResultSetMetaData接口怎么使用
2024-04-11

怎么使用API接口

这篇文章主要介绍“怎么使用API接口”,在日常操作中,相信很多人在怎么使用API接口问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用API接口”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!接口交互前
2023-06-16

TypeScript接口怎么使用

这篇文章主要讲解了“TypeScript接口怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“TypeScript接口怎么使用”吧!前言:TS的核心原则之一就是对所具有的结构 进行类型检
2023-06-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录