go语言接口定义

1,概览

1,go语言接口和传统面向对象语言(java)的接口不太一样.
2,go语言接口是隐式实现的,意思就是不需要给实现接口的类型规定必须
   实现某个接口。不像传统面向对象语言需要定义implement来实现接口。
3,只要某个类型实现了接口定义的所有方法,就认为这个类型实现了接口。
4,接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式、类型及结构

2,实例

type T interface {
    func1 (p1 string) (r1 string,err error)
    func2 (p2 string) (r2 string,err error)
    ...
}

3,注意:

实际开发过程中,Go语言的每个接口中的方法数量不会很多。
Go语言希望通过一个接口精准描述它自己的功能,而通过多
个接口的嵌入和组合的方式将简单的接口扩展为复杂的接口

go语言接口实现

1,概览

1,任意类型的方法全部包含了接口定义的方法,则此类型实现了接口。
   此类型可以接口类型,也可以是非接口类型
2,实现类型实现接口的实现关系是隐式的

2,接口实现的两大原则

1,接口的方法与实现接口的类型方法格式一致
2,接口中所有方法均被实现

注意:
    如果某个类型实现了接口的部分方法,类型对象调用方法的时候没有问题。如果是定义的接口变量调用方法的时候,会报错。

3,实例

package interfaceDemo

import (
    "fmt"
    "strconv"
)

type Idemo interface {
    func1(s string) int
    func2(i int) string
    //func3(p string) int
}

type Sdemo struct {
}

func (this *Sdemo) func1(s string) int {
    res, err := strconv.Atoi(s)
    if err != nil {
    panic(err)
    }
    return res
}

func (this *Sdemo) func2(i int) string {
    res := strconv.Itoa(i)
    return res
}

func Run() {

    sde := &Sdemo{}

    //sde.func1("5")

    var IdemoObj Idemo

    IdemoObj = sde

    fmt.Printf("value:%v,type:%T\n",IdemoObj.func2(5),IdemoObj.func2(5))
    fmt.Printf("value:%v,type:%T\n",IdemoObj.func1("5"),IdemoObj.func1("5"))

}

4,传统接口实现和go接口实现的区别

传统的派生式接口及类关系构建的模式,让类型间拥有强耦合的父子关系。这种关系一般会以“类
派生图”的方式进行。经常可以看到大型软件极为复杂的派生树。随着系统的功能不断增加,这棵
“派生树”会变得越来越复杂。

对于Go语言来说,非侵入式设计让实现者的所有类型均是平行的、组合的。如何组合则留到使用者
编译时再确认。因此,使用GO语言时,不需要同时也不可能有“类派生图”,开发者唯一需要关注的
就是“我需要什么?”,以及“我能实现什么?”。

go语言类型和接口的关系

1,概览

1,在Go语言中类型和接口之间有一对多和多对一的关系
2,一个类型可以实现多个接口,接口间互相不知道该类型实现的其他接口。
3,多个类型可以实现相同的接口,不论是一个类型实现接口,还是多个类型通过内嵌实现接口,
   接口本身不关心。只关心类型是否实现了接口。

Go语言接口的nil判断

1,概览

1,接口在底层的实现,分两部分,type和data。nil赋值给接口,则type,data都
为nil。假如把带有类型的nil复制给接口的时候,data为nil,type并非nil,此时
当前接口不等于nil

Go语言类型断言

1,概览

类型断言(Type Assertion)是一个使用在接口值上的操作,用于检查接口类型变量
所持有的值是否实现了期望的接口或者具体的类型

语法格式:
    1,普通断言
        var x interface{}
        value,ok := x.(T)
    2,switch断言
    switch 接口变量.(type) {
        case 类型1:
        // 变量是类型1时的处理
        case 类型2:
        // 变量是类型2时的处理
        …
        default:
        // 变量不是所有case中列举的类型时的处理
    }

2,实例

func Run() {

    //普通接口类型断言
    var x interface{}
    x = 10
    v1, ok1 := x.(int)
    v2, ok2 := x.(string)
    fmt.Println(v1, ok1)
    fmt.Println(v2, ok2)

    var y interface{}
    y = "goLang"
    v3, ok3 := y.(int)
    v4, ok4 := y.(string)
    fmt.Println(v3, ok3)
    fmt.Println(v4, ok4)

    //switch类型断言
    switchAsset(x)
    switchAsset(y)
}

//switch类型断言
func switchAsset(a interface{}) {
    switch a.(type) {
    case int:
        fmt.Println("switch int")
    case string:
        fmt.Println("switch string")
    case float64:
        fmt.Println("switch float64")
    default:
        fmt.Println("switch unknows")
    }
}

Go语言接口嵌套

1,概览

1,类似于结构体一样,go语言interface也可以互相嵌套出新的接口
2,一个接口可以包含一个或多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样

Go语言空接口类型

1,概览

1,空接口类型可以保存任何值,也可以从空接口中取出原值。
2,空接口的内部实现保存了对象的类型和指针。使用空接口保存一个数据的过程会比直接用数据对应类型的变量保存稍慢。
3,开发过程中,酌情使用空接口

2,空接口相关操作

1,空接口赋值

    var tmp interface{} = "val"

2,空接口取值

    var str string = tmp.(string) //类型断言

3,空接口比较

    var c interface{} = 100
    var d int = 100
    fmt.Println(c == d)

    注意:
        空接口在保存不同的值后,可以和其他变量值一样使用==进行比较操作,但是
            1,类型不同的空接口间的比较结果不相同
            2,不能比较空接口中的动态值,比如切片,map等等

        go语言容器,空接口可比较类型:
            map             宕机错误,不可比较
            切片([]T)     宕机错误,不可比较
            通道(channel) 可比较,必须由同一个 make 生成,也就是同一个通道才会是 true,否则为 false
            数组([容量]T)   可比较,编译期知道两个数组是否一致
            结构体         可比较,可以逐个比较结构体的值
            函数              可比较

3,实例

func emptyInterface(){
    //空接口赋值
    var any interface{}
    any = 1
    fmt.Println(any)
    any = "php"
    fmt.Println(any)
    any = false
    fmt.Println(any)

    fmt.Println("############finished##########")

    //从空接口获取值,接口断言
    var a int = 1
    var i interface{} = a
    var b int = i.(int)
    fmt.Println(b)


    fmt.Println("############finished##########")
    //空接口的值比较
    //空接口在保存不同的值后,可以和其他变量值一样使用==进行比较操作
    var v1 interface{} = 200
    var v2 int = 200
    fmt.Println( v1 == v2 )//true
    var v3 interface{} = "goLang"
    var v4 string = "goLang"
    fmt.Println( v3 == v4 )//true
    fmt.Println( v1 == v4 )//false
    //不能比较空接口中的动态值
    var d interface{} = []int{10}
    var c interface{} = []int{10}
    fmt.Println(d == c)//panic

}

Go语言空接口类型

1,概览

1,go语言容器,包括arr,slice,map都是提前定义了数据类型。那么如何在容器中保存不通类型的值呢,就用空接口实现
2,空接口可以保存任何类型这个特性可以方便地用于容器的设计

2,实例

testMap := make(map[interface{}]interface{})
testMap["abc"] = "def"
testMap[1] = "hhh"
testMap[2] = 3
testMap[true] = false
fmt.Println(testMap)
//map[true:false 1:hhh 2:3 abc:def]

var testSlice []interface{}
testSlice = append(testSlice,1)
testSlice = append(testSlice,"abc")
testSlice = append(testSlice,true)
fmt.Println(testSlice)
//[1 abc true]