interface的定义和声明方式

645 阅读2分钟

Golang interface关键字用来申明一组相关功能方法集合,是Go提供的抽象的主要手段。通过struct实现interface的所用声明来达到解耦,使用语法如下:

// package Interface
type InterfaceName interface{
    Method1()string
}

// Package Implement
type Implement struct {}

func (i Implement) Method() string {
    return "Hello, Interface"
}

// Package main

任何实现了Interface的struct都是可以使用该类型的变量引用。下面是对本人在interface定义和使用中提到的一些常用的“误用“的说明。

Don't define interface before needing it

预先定义的interface 即preemptive interface, 是不鼓励的,如果你只是实现一个功能,把功能暴露出来即可

Define Interface with Consumer, not Producer

通过前两条即可推理出,我们应该在Consumer中定义interface并且使用它作为函数的参数,在Producer中实现这些interface。这样还有一个好处是可以在consumer中很容易的mock 该producer,无需接触真正的实现。

Accepting interface & returns struct

Accepting interface

根据Postel’s law ”be liberal with what you accept, be conservative with what you do", 函数参数接收interface,扩大了函数的使用场景,能够接收更多的参数类型。例如下面example, CountCharA接口Reader, 可以使该函数

func CountCharA(r io.Reader) (int64, error){
    buf [10]byte
    for {
        nr, err := r.Read(buf)
        if nr > 0 {
            for _, b := range buf[0:nr]{
                if b == 'A'{
                    cnt++
                }
            }
        }
        
        if err != nil {
           if err != EOF{
               return 0, err
           }
           return cnt, nil
        }
    }
    return cnt, nil
}

// Usage
CountCharA(bytes.NewStringBuffer("this statement contains 3a"))
CountCharA(ioutil.ReadFile("file.txt"))

Returns struct

返回struct,可以保证使用者能够最大限度的使用我们函数结果,如果因为struct可以自由的转换成该struct实现的所有interface,而且便于修改,

但是凡是都例外, error interface,

另外一个情况是,当返回struct包含有非法状态时, 通过返回interface来控制struct实现的合法性,而无需在调用前检查其合法性。