@Author:Runsen

学习过Java,大家或多或少了解接口。接口是一种类型,它指定一个方法集,所有方法为接口类型就被认为是该接口。

文章目录

  • 接口
  • 接口内部实现
  • 指针方法值方法
  • 空接口

接口

在Go语言中,一个接口类型总是代表着某一种类型(即所有实现它的类型)的行为。一个接口类型的声明通常会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干方法声明。go 使用 type 关键字来定义接口,接口的声明类似于结构体,使用类型别名且需要关键字 interface,语法如下。代码来源:菜鸟教程。

type Name interface {Method1(param_list) return_typeMethod2(param_list) return_type...
}

go 中的接口,这个概念实际上是比较难懂的,来看一个demo:

package mainimport "fmt"type Person interface {getName() string
}type student struct {Name string sex string
}var stu = student{"Runsen","男"}func (stu student) getName() string {return stu.Name
}  // 这样student类型就实现了Person接口type teacher struct {Name string sex string
}var tea = teacher{"Runsen","男"}func (tea teacher) getName() string{return tea.Name
}  // 这样teacher类型就实现了Person接口func main() {fmt.Println(stu.getName()) //Runsenfmt.Println(tea.getName()) //Runsen
}

上面的代码定义了接口类型 Person ,接口中包含了一个不带参数、返回值为 string的方法 getName()。任何实现了方法 getName() 的类型 student和teacher,我们就说它实现了接口 Person 。

接口内部实现

接口内部的实现:

type iface struce{tab *iTabledata unsafe.Pointer
}

接口结构是包含两个字段的数据结构,第一个包含一个指向内部表的指针,这个内部表叫做iTable,包含子所存储的值的类型信息。iTable包含了已存储的值的类型信息已经值关联的一组方法。第二个字段指向存储值的指针,指向赋值的这个对象。

从内部实现来看,接口本身也是一种结构类型,只是编译器会对其做很多的限制。

  • 不能有自己的字段
  • 不能定义自己的方法
  • 只能声明方法,不能实现
  • 可嵌入其他接口类型

这些注意点和Java的接口完全一样。

指针方法值方法

实现接口有两种方法。上面我们都是使用值接受者(Value Receiver)来实现接口的。我们同样可以使用指针接受者(Pointer Receiver)来实现接口。

在此之前,我们需要了解下指针。
指针是存储变量内存地址的变量,表达了这个变量在内存存储的位置。就像我们常说:指针指向了变量。

Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

package mainimport "fmt"func main() {var a int = 1fmt.Printf("变量的地址: %x\n", &a) // 变量的地址: c0000140b8
}

在Go语言中关于指针的操作如下所示。

package mainimport "fmt"func main() {var a int= 1  /* 声明实际变量 */var ip *int        /* 声明指针变量 */ip = &a  /* 指针变量的存储地址 */fmt.Printf("a 变量的地址是: %x\n", &a  ) //a 变量的地址是: c0000140b8/* 指针变量的存储地址 */fmt.Printf("ip 变量储存的指针地址: %x\n", ip ) //ip 变量储存的指针地址: c0000140b8/* 使用指针访问值 */fmt.Printf("*ip 变量的值: %d\n", *ip ) //*ip 变量的值: 1
}

在函数接收者,可以使用指针方法和值方法。区别在于,用指针类型作为接收者,可以在函数/方法内部修改这个接收者的数据,而用值类型作为接收者,在函数/方法内部不能修改原接收者的数据。

接收者可以是指针类型,也可以是值类型,它们到底有什么区别?一开始学Go语言的时候,我也一头雾水。看下面的例子就明白了:

package main
import "fmt"type user struct {name stringage  int
}
// 值的
func (u user) PrintName() {fmt.Println(u.name)
}
// 指针的
func (u *user) PrintAge() {fmt.Println(u.age)
}
func main() {     var Runsen *user // 润森是指针类型的Runsen = &user{"Runsen", 20}  // 正常输出无误Runsen.PrintName()  // zhangsanRunsen.PrintAge() // 10var maoli user // 毛利是值类型maoli = user{"Maoli", 20} // 正常输出无误maoli.PrintName()  // lisimaoli.PrintAge() // 20// 以值的方式调用 一个定义在指针类型下的方法时,会隐式的转换值到指针,例中maoli.PrintAge() 就是这样
// 以指针的方式调用 一个定义在值类型下的方法时,会隐式的转换指针到值,例中Runsen.PrintName() 就是这样
// 相同:无论定义在哪种类型下,都可以访问到。
// 区别:只有定义在指针类型下的方法可以修改原变量的内容
}

指针类型的接收者之所以需要指针,就是因为它要改变原对象的值。 在上面的例子中,调用user的SetName方法时,编译器会帮你把user的指针传递给SetName方法。

空接口

一个不包含任何方法的接口,称之为空接口,形如:interface{}。因为空接口不包含任何方法,所以任何类型都默认实现了空接口。

举个例子,fmt 包中的 Println() 函数,可以接收多种类型的值,比如:int、string、array等。为什么,因为它的形参就是接口类型,可以接收任意类型的值。

下面就是Println接口源码

func Println(a ...interface{}) (n int, err error) {}

空接口表示为 interface{}。由于空接口没有方法,因此所有类型都实现了空接口。

package mainimport  "fmt"func describe(i interface{}) {  fmt.Printf("Type = %T, value = %v\n", i, i)
}func main() {  s := "Hello World"describe(s) //Type = string, value = Hello Worldi := 1 describe(i) // Type = int, value = 1strt := struct {name string}{name: "Runsen",}describe(strt) //Type = struct { name string }, value = {Runsen}}

感谢各位的阅读,文章的目的是分享对知识的理解,技术类文章我都会反复求证以求最大程度保证准确性,若文中出现明显纰漏也欢迎指出,我们一起在探讨中学习。

八、深入Go 编程语言接口相关推荐

  1. python接口测试-项目实践(八) 完成的接口类和执行脚本

    脱敏后脚本 projectapi.py: 项目接口类 # -*- coding:utf-8 -*- """ xx项目接口类 2018-11 dinghanhua &quo ...

  2. SQLite学习(八) - SQLite C编程接口

    老版本的SQLite编程接口很简单,只有5个接口.随着新功能的增加,新版本的SQLite有185个编程接口. 但是不用担心,核心API还是很容易理解的. 1. 先来介绍核心对象和接口 (1) 数据库连 ...

  3. Python学习八:数据库编程接口

    文章目录 一.数据库编程接口 1.1 连接对象 1.1.1 获取连接对象 1.1.2 连接对象的方法 2.1 游标对象 一.数据库编程接口 1.1 连接对象 1.1.1 获取连接对象 数据库连接对象主 ...

  4. UE4学习之路【八】通过蓝图接口制作一个简易门

    在第二期我制作了一个可以由玩家控制开关的简易门,传送门:UE4学习之路[二]制作一个简易门(上),是通过在门的蓝图类里使用Get Player Controller和Enable Input来开启玩家 ...

  5. Rust语言开发基础(八)Rust的接口及其实现

    2019独角兽企业重金招聘Python工程师标准>>> trait(特征)类似于其他语言中的interface或者protocol,指定一个实际类型必须满足的功能集合 一.如何理解t ...

  6. SUMO入门(八) - TraCI

    SUMO入门(八) - TraCI TraCI TraCI/Interfacing TraCI from Python TraCI 是 "Traffic Control Interface& ...

  7. 探索编程语言的本质:了解编程语言的定义与分类

    前言: 由于我看了一眼我的粉丝列表,发现好像关于开发语言的童鞋占比较多哈,所以出一下这篇专栏. 要关注的小伙伴可以提前订阅哈. 目录 前言: 引言 1.1. 编程语言的重要性 1.2. 本文的目的与结 ...

  8. Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明

    这里所说的高级接口是指面向通过认证的服务号开通的高级功能. 高级功能大致可以分类为: 用户接口 分组接口 客服接口(有别于之前介绍的多客服) 群发接口 多媒体接口 二维码接口 模板消息接口(不是所有账 ...

  9. wordpress 外部数据接口_WordPress Plugin API(插件接口)

    简介 本文介绍的是一些为 WordPress 插件开发者提供的 API (编程语言接口),以及如何调用这些接口. 阅读本文之前,请先参考开发一个插件,以便了解一些关于插件的概况和详情.文本着重于&qu ...

最新文章

  1. 原来AGILE就是这么一回事啊!
  2. 获取网页各种宽高的值
  3. 进入docker容器之后,找不到rosbag命令(ros已经安装)
  4. Swift之String的简单实用
  5. centos7.2安装mysql5.7_Centos7.2下使用YUM快速安装MySQL5.7的方法
  6. python定时器timer_python通过线程实现定时器timer的方法
  7. jquery方法.serializeArray()获取name和value并转为json数组
  8. Eclipse中部分快捷键
  9. 【入门4】数组 (今天刷洛谷了嘛)
  10. 线性阵列、圆周阵列、曲线阵列
  11. [转]最常用的15大Eclipse开发快捷键技巧
  12. Python使用exec自动生成代码并执行,同时得到返回的变量
  13. linux驱动基础开发1——linux 设备驱动基本概念-转
  14. 我们在 web 应用开发过程中经常遇到输出某种编码的字 符, 如 iso8859-1 等, 如何输出一个某种编码的字符串?...
  15. Shell脚本中使用awk进行空格分词
  16. Adblock PLus 插件chrome用
  17. 国产谷歌地球,地形分析秒杀同款地图软件
  18. HTML期末学生大作业-视频影视网页html+css+javascript(带报告册)
  19. 戴尔游匣7559更换C面和D面以及升级内存硬盘教程
  20. 计算机内存分配、管理

热门文章

  1. linux / scp 详解
  2. android 自动补全方法,Android零基础入门|自动完成文本框AutoCompleteTextView
  3. CPU方案简介UIS8190 - LTE CAT.1模块
  4. 百度AI原生云实践: 基于容器云打造 AI 开发基础设施
  5. mysql授权用户主机_MySQL用户授权(GRANT)
  6. 交大c语言作业答案,西安交大c语言作业及答案详解.docx
  7. pci-e串口卡linux 驱动下载,万能PCI串口卡驱动下载
  8. layui select 修改_layui修改select的值的方法
  9. python用input输入列表有缺陷_Python 三程三器的那些事
  10. 记-PHPExcel下载