GO接口详解

来源:互联网 发布:股票配资子账户软件 编辑:程序博客网 时间:2024/06/11 19:09

1、GOLANG中的接口定义语法:

type InterfaceName interface {

  //方法列表

}


2、GOLANG接口实现

golang中的接口实现不向其他语言(c++/java)需要强制声明实现该接口,而是只要类中的方法包含了接口中的方法,那么该类就实现了那个接口。

java接口实现语法演示:
interface Speaker {
void speak();
}


class Cat implements Speaker  //需要强制声明实现该接口
{
@Override
public void speak() {
// TODO Auto-generated method stub
//...
}

}

golang接口实现语法演示:
type LessAdder interface {
    Less(INTEGER) bool
    Add(INTEGER)
}
type INTEGER int
func (a INTEGER) Less(b INTEGER) bool {
    return a < b
}
func (a *INTEGER) Add(b INTEGER) {
    *a += b
}

从golang实现接口的代码上可以看出,在定义类型时,无需显示声明实现该接口,甚至INTEGER类型都不知道接口LessAdder的存在。

3、GOLANG接口赋值注意事项

(1) 类型T的对象赋值给接口变量时,要求类型T的所有方法的接收器类型必须是T
(2) 类型*T的对象赋值给接口变量时,类型T的方法接收器类型可以是T或者*T
(3) 在golang中,只要两个接口具有相同的方法列表,那么他们就是等同的,就可以相互赋值;如果一个接口的方法列表包含了另一个接口的方法列表,那么可以将大的接口变量赋值给小的接口变量

类型T的对象赋值给接口变量时,要求类型T的所有方法的接收器类型必须是T
e.g.
package main
import "fmt"
type LessAdder interface {
    Less(INTEGER) bool
    Add(INTEGER)
}
type INTEGER int
func (a INTEGER) Less(b INTEGER) bool {
    return a < b
}
func (a *INTEGER) Add(b INTEGER) {
    *a += b
}
func main() {
    var a INTEGER = 10
    var b LessAdder = a  //有问题
    fmt.Println(b.Less(20))
    b.Add(40)
    fmt.Println(a)
}
编译运行:

C:/go/bin/go.exe run test.go [E:/project/go/lx/src]

# command-line-arguments

.\test.go:23: cannot use a (type INTEGER) as type LessAdder in assignment:

INTEGER does not implement LessAdder (Add method has pointer receiver)

错误: 进程退出代码 2.

e.g.
package main
import "fmt"
type LessAdder interface {
    Less(INTEGER) bool
    Add(INTEGER)
}
type INTEGER int
func (a INTEGER) Less(b INTEGER) bool {
    return a < b
}
func (a INTEGER) Add(b INTEGER) { //该方法修改的是形参a的值,并没有真正修改main函数中的变量a
    a += b
}
func main() {
    var a INTEGER = 10
    var b LessAdder = a
    fmt.Println(b.Less(20))
    b.Add(40)
    fmt.Println(a)
}
编译运行:

C:/go/bin/go.exe run test.go [E:/project/go/lx/src]

true

10

成功: 进程退出代码 0.

OK,这次编译通过,但是这段代码是有问题的,参见代码注释。

类型*T的对象赋值给接口变量时,类型T的方法接收器类型可以是T或者*T

e.g.

package main
import "fmt"
type LessAdder interface {
    Less(INTEGER) bool
    Add(INTEGER)
}
type INTEGER int
func (a INTEGER) Less(b INTEGER) bool { //接收器类型为INTEGER
    return a < b
}
func (a *INTEGER) Add(b INTEGER) { //接收器类型为*INTEGER
    *a += b
}
func main() {
    var a INTEGER = 10
    var b LessAdder = &a
    fmt.Println(b.Less(20))
    b.Add(40)
    fmt.Println(a)
}
编译运行:

C:/go/bin/go.exe run test.go [E:/project/go/lx/src]

true

50

成功: 进程退出代码 0.

OK。从上面的代码可以看出,当接口变量的值是*T时,接收器的类型可以是T或*T

在golang中,只要两个接口具有相同的方法列表,那么他们就是等同的,就可以相互赋值;

如果一个接口的方法列表包含了另一个接口的方法列表,那么可以将大的接口变量赋值给小的接口变量。

e.g.

package one
type ReadWriter interface {
    Read(buff []byte) (n int, err error)
    Write(buff []byte) (n int, err error)
}

package two
type IStream interface {
    Write(buff []byte) (n int, err error)
    Read(buff []byte) (n int, err error)
}

上面定义的接口one.ReadWriter和two.IStream就是等价的,对应的接口变量可以相互赋值。

    var file1 one.ReadWriter=new(os.File)
    var file2 two.IStream=file1
    var file3 one.ReadWriter=file2


e.g.

package three
type Writer interface {
    Write([]byte) (int, error)
}

上面定义的Writer接口是one.ReadWriter和two.IStream接口的子接口,所以可以将one.ReadWriter和two.IStream类型变量赋值给three.Writer接口变量。
    var file1 one.ReadWriter=new(os.File)
    var file2 three.Writer=file1