package main

import "fmt"

type Shaper interface {
Area() float32
} type Square struct {
side float32
} func (sq *Square) Area() float32 {
return sq.side * sq.side
} func main() {
sq1 := new(Square)
sq1.side = 5 var areaIntf Shaper
areaIntf = sq1
// shorter,without separate declaration:
// areaIntf := Shaper(sq1)
// or even:
// areaIntf := sq1
fmt.Printf("The square has area: %f\n", areaIntf.Area())
}

  

上面的程序定义了一个结构体 Square 和一个接口 Shaper,接口有一个方法 Area()

在 main() 方法中创建了一个 Square 的实例。在主程序外边定义了一个接收者类型是 Square 方法的 Area(),用来计算正方形的面积:结构体 Square 实现了接口 Shaper 。

所以可以将一个 Square 类型的变量赋值给一个接口类型的变量:areaIntf = sq1 。

现在接口变量包含一个指向 Square 变量的引用,通过它可以调用 Square 上的方法 Area()。当然也可以直接在 Square 的实例上调用此方法,但是在接口实例上调用此方法更令人兴奋,它使此方法更具有一般性。接口变量里包含了接收者实例的值和指向对应方法表的指针。

这是 多态 的 Go 版本,多态是面向对象编程中一个广为人知的概念:根据当前的类型选择正确的方法,或者说:同一种类型在不同的实例上似乎表现出不同的行为。

如果 Square 没有实现 Area() 方法,编译器将会给出清晰的错误信息:

cannot use sq1 (type *Square) as type Shaper in assignment:
*Square does not implement Shaper (missing Area method)

  如果 Shaper 有另外一个方法 Perimeter(),但是Square 没有实现它,即使没有人在 Square 实例上调用这个方法,编译器也会给出上面同样的错误。

扩展一下上面的例子,类型 Rectangle 也实现了 Shaper 接口。接着创建一个 Shaper 类型的数组,迭代它的每一个元素并在上面调用 Area() 方法,以此来展示多态行为:

package main

import "fmt"

type Shaper interface {
Area() float32
} type Square struct {
side float32
} func (sq *Square) Area() float32 {
return sq.side * sq.side
} type Rectangle struct {
length, width float32
} func (r Rectangle) Area() float32 {
return r.length * r.width
} func main() { r := Rectangle{5, 3} // Area() of Rectangle needs a value
q := &Square{5} // Area() of Square needs a pointer
// shapes := []Shaper{Shaper(r), Shaper(q)}
// or shorter
shapes := []Shaper{r, q}
fmt.Println("Looping through shapes for area ...")
for n, _ := range shapes {
fmt.Println("Shape details: ", shapes[n])
fmt.Println("Area of this shape is: ", shapes[n].Area())
}
}

  在调用 shapes[n].Area() 这个时,只知道 shapes[n] 是一个 Shaper 对象,最后它摇身一变成为了一个 Square 或 Rectangle 对象,并且表现出了相对应的行为。

在调用 shapes[n].Area() 这个时,只知道 shapes[n] 是一个 Shaper 对象,最后它摇身一变成为了一个 Square 或 Rectangle 对象,并且表现出了相对应的行为。

package main

import "fmt"

type stockPosition struct {
ticker string
sharePrice float32
count float32
} /* method to determine the value of a stock position */
func (s stockPosition) getValue() float32 {
return s.sharePrice * s.count
} type car struct {
make string
model string
price float32
} /* method to determine the value of a car */
func (c car) getValue() float32 {
return c.price
} /* contract that defines different things that have value */
type valuable interface {
getValue() float32
} func showValue(asset valuable) {
fmt.Printf("Value of the asset is %f\n", asset.getValue())
} func main() {
var o valuable = stockPosition{"GOOG", 577.20, 4}
showValue(o)
o = car{"BMW", "M3", 66500}
showValue(o)
}

  数据类型实现了接口,就能使用以接口变量为参数的方法

备注:

有的时候,也会以一种稍微不同的方式来使用接口这个词:从某个类型的角度来看,它的接口指的是:它的所有导出方法,只不过没有显式地为这些导出方法额外定一个接口而已。

golang interface接口的更多相关文章

  1. golang面向对象和interface接口

    一. golang面向对象介绍 1.golang也支持面向对象编程,但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言.2.golang没有类(class),golang语言的结合体(struc ...

  2. Golang 入门系列(四)如何理解interface接口

    前面讲了很多Go 语言的基础知识,包括go环境的安装,go语言的语法等,感兴趣的朋友,可以先看看之前的文章.https://www.cnblogs.com/zhangweizhong/category ...

  3. Golang之接口(interface)

    Golang最重要的接口,,,, package main import ( "fmt" ) //interface类型默认是指针 /* 接口的实现 Golang中的接口,不需要显 ...

  4. Golang基础(8):go interface接口

    一:接口概要 接口是一种重要的类型,他是一组确定的方法集合. 一个接口变量可以存储任何实现了接口方法的具体值.一个重要的例子就是io.Reader和io.Writer type Reader inte ...

  5. go interface接口

    一:接口概要 接口是一种重要的类型,他是一组确定的方法集合. 一个接口变量可以存储任何实现了接口方法的具体值.一个重要的例子就是io.Reader和io.Writer type Reader inte ...

  6. [golang note] 接口使用

    侵入式接口 √ 在其他一些编程语言中,接口主要是作为不同组件之间的契约存在,即规定双方交互的规约. √ 对契约的实现是强制的,即必须确保用户的确实现了该接口,而实现一个接口,需要从该接口继承. √ 如 ...

  7. Golang的接口

    当一只鸟走路像鸭子,游泳像鸭子,叫起来也像鸭子,那么我们就认为它就是鸭子. Duck typing 的理念因此比喻得名. Golang 通过 interface 实现 duck typing. Eff ...

  8. golang(08)接口介绍

    原文链接 http://www.limerence2017.com/2019/09/12/golang13/#more 接口简介 golang 中接口是常用的数据结构,接口可以实现like的功能.什么 ...

  9. as3.0 interface接口使用方法

    [转]as3.0 interface接口使用方法 AS在2.0的时候就支持接口了 接口能够让你的程序更具扩展性和灵活性,打个例如 比方你定义了一个方法 代码: public function aMet ...

随机推荐

  1. LwIP raw api下使用tcp keep alive

    // The following code is implemented after tcp_new() or in tcp_connected call back... xxx_connected( ...

  2. PHP PDO prepare()、execute()和bindParam()方法详解

    每次将查询发送给MySQL服务器时,都必须解析该查询的语法,确保结构正确并能够执行.这是这个过程中必要的步骤,但也确实带来了一些开销.做一次是必要的,但如果反复地执行相同的查询,批量插入多行并只改变列 ...

  3. Jade简单教程

    Express框架里内嵌了Jade模板引擎.正好项目里也要用到,本篇整理了下Jade的相关用法. 安装与执行 标签和属性 多行文本 变量 语句 Mixin 模板 注释 过滤器 安装与执行 安装很简单: ...

  4. Java 类的生命周期

    类从被加载到JVM内存中开始,到卸载出内存为止,它的整个生命周期包括: 加载(Loading)-->验证(Verification)-->准备(Preparation)-->解析(R ...

  5. bat批处理(二):%0 %1——给批处理脚本传递参数

    初次接触批处理脚本觉得有点意思,所以决定写一个小功能试验一下,谁知刚一开始就发现遇到了麻烦,本想着使用参数来控制程序的运行结果,可是参数怎么传进去呢,于是研究了一番,最终发现这个参数的传递与main函 ...

  6. 原生socket请求url获取状态码、消息报头、响应正文

    需求: (1)使用socket及ssl模块写通用的web客户端 (2)向服务器发起请求 (3)接受响应内容并解析出状态码.消息报头.响应正文 (4)最核心的函数: 输入一个url,返回状态码.消息报头 ...

  7. shiro与threamleaf的整合

    1.添加依赖 2.在配置类中添加shiroDialect

  8. as3 三行三列 布满9个为一个界面

    var n:int=int(iconIndex/3); e.x =(int(n/3)*3+iconIndex%3)*557; e.y = int(iconIndex / 3) % 3 * 260; i ...

  9. AS3 localToGlobal、globalToLocal方法的总结

    (1).localToGlobal (point)   把point看成在(1)内部,计算出该point相当于stage的坐标 (2).globalToLocal (point)   point为全局 ...

  10. android -chrome 调试

    在chrome上 输入 chrome://inspect/ 连接手机,配置 监听8000,和8080端口 cordova默认是8000端口 如果出现白屏:原因:google在首次加载时,要进行服务器连 ...