Go关键字--interface

原创 2018年04月15日 20:50:36

interface

接口就是定义了0个或多个方法的集合,它是两个事物对接的一个规范。实现了这个接口,就符合了这个规范。接口中只能声明方法,不能定义字段,也不能实现方法。这一点与java的interface还不太一样,在java的interface中,可以定义常量字段,而golang的interface中只能有方法。下边来看看定义一个接口的语法:

type Message interface{
    Read() string
    Write(str string)
}

上边的示例中,定义了一个名为Message的接口,接口中有两个方法,分别是Read和Write。Read方法返回一个string类型值,而Write方法接收一个string类型的参数。定义接口的语法非常简单。

接口实现与赋值

接口实现,就是某一个类型拥有这个接口全部声明的方法。
golang中任何类型,都可以去实现某一个或多个接口。以int类型为原型,定义一个新的类型myInt。让myInt类型来实现接口msg。示例代码如下:

package main

import (
    "fmt"
)

// 定义接口,接口名称是msg,接口中有一个方法
type msg interface {
    write(v string)
}

// 根据int定义一个新的类型myInt
type myInt int

// 给myInt类型添加方法
func (r myInt) write(v string) {
    fmt.Println(v)
}

func main() {
    var m msg = myInt(3)
    m.write("hello wolrd")
}

从上边的示例代码可知,myInt类型实现了msg接口。当类型A实现了接口B之后,类型A的变量就可以被赋值给接口B类型的变量,如上边代码中,将myInt类型变量赋值给msg接口类型变量m。

在golang中,能够实现接口的不仅仅是由struct定义的结构体类型,可以是任意能够添加方法的类型,所谓任意能够添加方法的类型,就是本包中的类型,因为golang只允许给本包中的类型添加方法。

假如一个接口没有任何方法,那么所有的类型都实现了这个接口。没有方法的接口如下边示例所示:

package main

import (
    "fmt"
)

type Any interface{}

func main() {
    var fromInt Any = 10
    var fromStr Any = "hello world"
    var fromFloat Any = 3.14
    fmt.Println(fromInt, fromStr, fromFloat)
}

输出结果是:

10 hello world 3.14

上边示例代码中,Any是一个没有任何方法的接口,在变量定义中,分别使用整型,字符串类型,浮点型来初始化了Any接口类型的变量,都能正常运行。

golang给我们提供了一个更为精简的没有方法的接口类型,即:

interface{}

根据之前的观点,任何类型都实现了没有方法的接口。上边的代码也可以修改成下边的样式:

package main

import (
    "fmt"
)

func main() {
    var fromInt interface{} = 10
    var fromStr interface{} = "hello world"
    var fromFloat interface{} = 3.14
    fmt.Println(fromInt, fromStr, fromFloat)
}

interface{}类型的变量,可以使用任何类型的值来赋值,可以称之为万能类型。

接口组合

接口组合,就是在接口中引入另一个接口。接口被引入后,外层接口就接收了被引入接口的所有方法。示例代码如下:

type Reader interface {
    Read() string
}

type Writer interface {
    Write(str string)
}

type ReaderWriter interface {
    Reader
    Writer
}

Reader接口有一个方法Read, Writer接口中有一个方法Write, 而ReaderWriter组合了Reader和Writer接口,那么ReaderWriter接口就拥有了Read和Write方法。如果要实现ReaderWriter这个接口,就必须拥有Read和Write两个方法,缺一不可。

下边来定义一个类型实现ReaderWriter接口,示例代码如下:

type file struct {
}

func (r *file) Read() string {
    return time.Now().Format("2006-01-02 15:04:05")
}

func (r *file) Write(str string) {
    fmt.Println(str)
}

类型查询

有两个类型都实现了某一个接口,这两个类型的变量都可以被赋值给这个接口类型的变量。接口查询,就是根据这个接口类型变量,查找到赋值给它的那个变量的类型。之前在type关键字讲解中将结果使用.(type)实现类型查询的方法,在这了就不在累述,下边来介绍一下通过断言方式实现接口查询,断言查询的语法格式是:

ret, flag := obj.(dt)

obj表示接口类型变量,dt表示猜测的类型,flag就是猜测的结果。如果flag为true,表示obj由dt类型的变量赋值。如果flag为false,表示obj不是由dt类型变量赋值。不管flag是true还是false,ret都是之前给obj赋值的那个变量。
如下边示例代码:

package main

import (
    "fmt"
)

type B interface {
    Say(str string)
}

type A struct {
}

func (r A) Say(str string) {
    fmt.Println(str, "A结构体:")
}

type C struct {
}

func (r C) Say(str string) {
    fmt.Println(str, "C结构体:")
}

func main() {
    // 将A类型变量赋值给B接口类型变量b
    var b1 B = A{}
    var b2 B = C{}

    // 判断b1是否由A类型变量赋值
    if b, ok := b1.(A); ok {
        b.Say("b1 是")
    } else {
        b.Say("b1 不是")
    }

    // 判断b2是否由A类型变量赋值
    if b, ok := b2.(A); ok {
        b.Say("b2 是")
    } else {
        b.Say("b2 不是")
    }
}

输出信息是:

b1 是 A结构体:
b2 不是 A结构体:

上边示例中,接口类型变量b1由A类型变量赋值, b2由C类型变量赋值。通过类型查询,查询这个接口变量是否由某个指定类型变量赋值。

接口查询

接口查询,就是在一个接口变量中,去判断那个把值赋给这个接口变量的对象究竟有没有实现另一个接口,这个所谓的另一个接口,就是我要查询的那个接口。

通过接口查询,我们来充分的挖掘这个对象的更多功能,请看这段示例代码:

package main

import (
    "fmt"
)

type R interface {
    Read()
}

type W interface {
    Write(name string)
}

type RW interface {
    R
    W
}

type log struct {
    name []string
    r    int
}

func (t *log) Read() {
    if len(t.name) > t.r {
        fmt.Println(t.name[t.r])
        t.r++
    } else {
        fmt.Println("empty")
    }
}
func (t *log) Write(name string) {
    t.name = append(t.name, name)
    fmt.Println("wirte success.", t.name)

}
func main() {
    var w W = &log{}
    w.Write("interface W")
    if val, ok := w.(RW); ok {
        val.Read()
    }
}

上边代码中的R接口,声明了Read方法,W接口,声明了Write方法。RW接口通过组合R与W,相当于声明了Read方法与Write方法。

log类实现了上边的3个接口。在实例化log后,将对象赋值给R接口变量和W接口变量。那么问题就来了,R接口变量只能访问Read方法;W接口变量只能访问Write方法。虽然log类型的对象拥有Write和Read方法,但是在赋值给不同的接口变量后,log类型对象本身的方法被隐藏了。接口查询,首先获取W接口变量w赋值的那个对象,即log指针类型对象,然后查询log对象是否实现了接口RW。
语法格式如下:

    val, ok := w.(RW)

如果w接口变量的赋值对象实现了RW接口,则ok为true,val为log对象,如果w接口变量的赋值对象没有实现RW接口,则ok为false,val为nil

go - interface 接口

Interface 1. 概述   Interface 是一组抽象方法(未具体实现的方法/仅包含方法名参数返回值的方法)的集合,有点像但又不同于其他编程语言中的 interface 。   如果实现...
  • chuangrain
  • chuangrain
  • 2013-07-17 18:03:57
  • 10893

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

Go不是一种典型的OO语言,它在语法上不支持类和继承的概念。 没有继承是否就无法拥有多态行为了呢?答案是否定的,Go语言引入了一种新类型—Interface,它在效果上实现了类似于C++的“多态”概念...
  • slvher
  • slvher
  • 2015-03-20 15:28:13
  • 5873

Golang-interface(一 基本使用)

Go中接口介绍和使用。
  • Crazy__Programmer
  • Crazy__Programmer
  • 2014-05-12 08:18:37
  • 13161

Go语言基础:Interface

转:http://xhrwang.me/2014/12/29/golang-fundamentals-8-interface.html我们知道 Golang 中没有 class 的概念,而是通过 in...
  • uudou
  • uudou
  • 2016-09-07 07:38:46
  • 4457

go中的interface

用了9年的C++,1年的C#,最近改用go语言开发,深感go语言的设计简单,其设计宗旨也是less is more,它极大的加快了开发速度。 go语言吸取了很多现代语言的优点,一个比较重要的特性就是...
  • jacob_007
  • jacob_007
  • 2016-12-10 10:57:28
  • 1927

JSON与Go

介绍 JSON(JavaScript Object Notation)是一种简单的数据交换格式。从语法上来说,它综合了JavaScript的对象(objects)和列表(lists)。通常用于在...
  • zhjih123
  • zhjih123
  • 2014-07-13 19:00:09
  • 1432

Go语言_类型转换_interface与强类型(int,string...)转换

Go语言是门强类型语言,因此也导致了非常多的问题, interface{} 任意类型 不能随意的转换为其他类型 若要进行类型转换,需要进行类型的断言 示例代码: // Convert p...
  • u010003835
  • u010003835
  • 2016-06-28 17:18:41
  • 10450

go interface 转 string,解析json

package main import ( "encoding/json" "fmt" ) var user map[string]interface{} func main() { us...
  • aqiang912
  • aqiang912
  • 2015-09-29 12:02:52
  • 983

golang技术随笔(一)深入理解interface

Go语言的主要设计者之一罗布·派克( Rob Pike)曾经说过,如果只能选择一个Go语言的特 性移植到其他语言中,他会选择接口。可见接口在golang中的地位,及其对gloang这门语言所带来的活力...
  • justaipanda
  • justaipanda
  • 2015-01-26 19:13:47
  • 25471

go []Type(数组) 无法直接转化为 []interface{}(can't I assign any slice to an []interface{})

Introduction Given that you can assign a variable of any type to an interface{}, often people will ...
  • xiuye2015
  • xiuye2015
  • 2017-02-24 22:40:56
  • 974
收藏助手
不良信息举报
您举报文章:Go关键字--interface
举报原因:
原因补充:

(最多只允许输入30个字)