基本定义

Go 官方对于接口的定义是一句话:An interface type is defined as a set of method signatures. 翻译过来就是,一个接口定义了一组方法的集合。这和 Java 和 PHP 的接口类似,定义一组方法而不定义方法的具体实现。但是与 Java 和 PHP 迥然不同的地方在于 Go 不需要显式的声明 implements 关键词来继承接口,一个类型只要实现了接口中的所有方法,就视作继承了该接口,是隐式实现的。来看一个基本的使用示例:

// 定义一个平台接口,包含一个支付方法
type Platform interface {
Pay(amount int) error
} // 微信平台
type Wechat struct{} func (w *Wechat) Pay(amount int) error {
fmt.Printf("wechat amount: %d\n", amount)
return nil
} // 支付宝平台
// 任意值都可以实现接口,并非一定需要struct
type Alipay int func (a Alipay) Pay(amount int) error {
fmt.Printf("alipay amount: %d, a: %d\n", amount, a)
return nil
} func ExamplePlatform() {
var (
p Platform
w = Wechat{}
a Alipay = 1
)
p = &w
p.Pay(2) p = &a
p.Pay(3) // 这种写法会报错
// p = w
p = a
p.Pay(4) // Output:
// wechat amount: 2
// alipay amount: 3, a: 1
// alipay amount: 4, a: 1
}

在这个示例中,我们定义了一个 Platform 接口和两个结构体,分别使用了值接收器和指针接收器来实现了 Platform 接口。p = w 这行代码会报错,究其原因是,对于使用指针接收器实现的接口的 Wechat,只有它的指针会实现接口,值不会实现;而对于值实现接口的 Alipay,指针和值都会实现接口。所以 p = a 可以正常运行。

接口嵌套

接口可以嵌套另一个接口:

// 定义一个平台接口,包含一个支付方法
type Platform interface {
Pay(amount int) error
User
} type User interface {
Login()
Logout()
} // 微信平台
type Wechat struct{} func (w *Wechat) Pay(amount int) error {
fmt.Printf("wechat amount: %d\n", amount)
return nil
} func (w *Wechat) Login() {}
func (w *Wechat) Logout() {}

此时,Wechat 即实现了 Platform 接口,也实现了 User 接口。

接口类型断言

再来看一个很复杂的例子,我们将上面的代码稍作修改,将 WechatLogin Logout 提到另一个结构中,然后使用类型断言判断 Wechat 是否实现了 User 接口:

// 定义一个平台接口,包含一个支付方法
type Platform interface {
Pay(amount int) error
User
} type User interface {
Login()
Logout()
} type UserS struct {
} func (u *UserS) Login() {}
func (u *UserS) Logout() {} // 微信平台
type Wechat struct {
UserS
} func (w *Wechat) Pay(amount int) error {
fmt.Printf("wechat amount: %d\n", amount)
return nil
} func ExamplePlatform() {
var (
p Platform
w = Wechat{}
)
p = &w
p.Pay(2) // 类型断言
_, ok := p.(User)
fmt.Println(ok) // Output:
// wechat amount: 2
// true
}

空接口

Go 1.18 新增了一个新的变量类型:any,其定义如下:

type any = interface{}

其实 any 就是一个空接口,对于空接口而言,它没有任何方法,所以对于任意类型的值都相当于实现了空接口,这个概念和另一个编程概念十分相似,它就是大名鼎鼎的泛型。在 Go 语言中,fmt.Println 函数的接收值正是一个 any

func Println(a ...any) (n int, err error) {
return Fprintln(os.Stdout, a...)
}

使用空接口搭配类型断言,我们可以设计出一个简单的类型转换函数,它将任意类型的值转为 int:

func ToInt(i any) int {
switch v := i.(type) {
case int:
return v
case float64:
return int(v)
case bool:
if v {
return 1
}
return 0
case string:
vint, _ := strconv.Atoi(v)
return vint
} return 0
}

Go 之烧脑的接口的更多相关文章

  1. Swift 烧脑体操(二) - 函数的参数

    前言 Swift 其实比 Objective-C 复杂很多,相对于出生于上世纪 80 年代的 Objective-C 来说,Swift 融入了大量新特性.这也使得我们学习掌握这门语言变得相对来说更加困 ...

  2. 个人永久性免费-Excel催化剂功能第85波-灵活便捷的批量发送短信功能(使用腾讯云接口)

    微信时代的今天,短信一样不可缺席,大系统都有集成短信接口.若只是临时用一下,若能够直接在Excel上加工好内容就可以直接发送,这些假设在此篇批量群发短信功能中都为大家带来完美答案. 业务场景 不多说, ...

  3. App开发:模拟服务器数据接口 - MockApi

    为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...

  4. 干货来袭-整套完整安全的API接口解决方案

    在各种手机APP泛滥的现在,背后都有同样泛滥的API接口在支撑,其中鱼龙混杂,直接裸奔的WEB API大量存在,安全性令人堪优 在以前WEB API概念没有很普及的时候,都采用自已定义的接口和结构,对 ...

  5. 12306官方火车票Api接口

    2017,现在已进入春运期间,真的是一票难求,深有体会.各种购票抢票软件应运而生,也有购买加速包提高抢票几率,可以理解为变相的黄牛.对于技术人员,虽然写一个抢票软件还是比较难的,但是还是简单看看123 ...

  6. Java基础Map接口+Collections工具类

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  7. Java基础Map接口+Collections

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  8. java基础_集合List与Set接口

    List接口继承了Collection的方法  当然也有自己特有的方法向指定位置添加元素   add(索引,添加的元素); 移除指定索引的元素   remove(索引) 修改指定索引的元素   set ...

  9. 【WCF】自定义错误处理(IErrorHandler接口的用法)

    当被调用的服务操作发生异常时,可以直接把异常的原始内容传回给客户端.在WCF中,服务器传回客户端的异常,通常会使用 FaultException,该异常由这么几个东东组成: 1.Action:在服务调 ...

  10. PHP以接口方式实现多重继承(完全模拟)--学习笔记

     1.UML类图: 2.PHP代码: <?php /** * Created by PhpStorm. * User: andy * Date: 16-11-23 * Time: 下午7:57 ...

随机推荐

  1. freeswitch如何判断挂机方

    概述 freeswitch作为VOIP的软交换平台,需要对呼叫的信息做判断和归类. 常见的呼叫信息中,挂机方向的信息对于话单统计有很大的用处. 但是fs的原始话单和日志中并没有挂机方向的信息. 环境 ...

  2. docker容器常用操作

    1.查看运行容器 docker ps:  2.查看所有容器 docker ps -a:  3.查看容器的日志 docker logs 容器名称/容器ID: 4.运行镜像 docker run --na ...

  3. Laravel - 使用 DB facade 实现CURD

    <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades ...

  4. [转帖]【linux命令学习】— sar 命令学习

    https://blog.csdn.net/u013332124/article/details/101075521 一.命令使用介绍 sar命令全称 System Activity Report,它 ...

  5. [转帖]clickhouse 超底层原理& 高可用集群 实操(史上最全)

    https://www.cnblogs.com/crazymakercircle/p/16718469.html 文章很长,而且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵 ...

  6. [转帖]Nginx 保留 Client 真实 IP

    https://lqingcloud.cn/post/nginx-01/#:~:text=%E5%9C%A8%20Nginx%20%E4%B8%AD%E5%8F%AF%E4%BB%A5%E9%80%9 ...

  7. [转帖]PostgreSQL 统计所有数据表各自的总行数

    一般来说,可以使用 count(*) 来获取具体某张表的总行数: SELECT count(0) FROM t_user; 如果想获得所有表的行数信息,可以使用以下 SQL 语句: SELECT re ...

  8. [转帖]pyinstaller实现将python程序打包成exe文件

    https://www.cnblogs.com/blogzyq/p/13939739.html 如果我们想要在一个没有python以及很多库环境的电脑上使用我们的小程序该怎么办呢? 我们想到,在Win ...

  9. [转帖]12.JVM运行时数据区之虚拟机栈概述

    https://blog.csdn.net/u011069294/article/details/107050001 目录 1. 内存中的栈与堆 2.栈的优点 1. 内存中的栈与堆 栈是运行时单位,堆 ...

  10. CoreMark简单学习

    CoreMark简单学习 下载 https://github.com/eembc/coremark-pro 需要注意, 其实coremark是有两组. 一组是coremark 一组是 coremark ...