• Golang 语言接口的定义与实现


    Golang 语言接口的定义与实现

    go语言的接口(接口属于对象)定义使用了duck typing这个思想。下面来看go语言的一个函数代码:

    1. func isDuck(duck Duck) bool {
    2. return duck.AmDuck()
    3. }

    这里的isDuck函数被称为使用者,它使用了传入duck的amDuck()函数,因此duck被称为实现者。

    go语言接口由使用者定义,因为使用者用到了amDuck()这个函数,因此传入的duck接口需要定义amDuck()这个方法,这种思维更符合duck typing的思维,使用者觉得传入的对象拥有我需要的功能,我就认为你是这个接口类型。

    而传统的接口定义是反着来的,首先是实现者自己定义方法,使用者需要查看实现者定义了哪些方法,看自己是否能够使用。

    新建一个 demo 文件夹,在 demo 文件夹下新建 go.mod 文件和 main.go 文件,再在 demo 文件夹下新建一个 yellow文件夹,在 yellow 文件夹下新建一个 SmallDuck.go 文件

    go mod init demo

    go语言接口定义代码:

    1. type Duck interface {
    2. AmDuck() bool
    3. }

    go语言接口的子类实现:

    1. package yellow //yellow文件夹
    2. import "fmt"
    3. type SmallDuck struct {
    4. Foot int
    5. }
    6. func (smallDuck SmallDuck) AmDuck() bool {
    7. if smallDuck.Foot == 2 {
    8. return true
    9. }
    10. return false
    11. }
    12. func (smallDuck SmallDuck) String() string {
    13. return fmt.Sprintf("foot is %d", smallDuck.Foot)
    14. }

    struct如果实现了Amduck()的话,它就会被认为是Duck的实现类,这种隐式的接口实现定义,既能检查传入的类是否实现了AmDuck方法,又能实现以接口方式作为传入参数的效果。

    需要注意的是实现类的名称和属性以及方法名称都要大写,其它包才可以进行调用,否则将会出现报错

    go语言接口的使用:

    1. package main
    2. import "demo/yellow"
    3. func isDuck(duck Duck) bool {
    4. return duck.AmDuck()
    5. }
    6. type Duck interface {
    7. AmDuck() bool
    8. }
    9. func main() {
    10. duck := yellow.SmallDuck{2}
    11. print(isDuck(duck))
    12. }

    isDuck传入的参数被定义为一个接口,而这里传入的是我们的实现类,实现了解耦的效果

    go语言有三大常用的系统接口,Stringer,Reader,Writer。

    Stringer接口

    Stringer接口包含了String方法,它的作用和java的toString一样,我们在打印重写了String方法这个对象的时候,会打印出返回的string值。定义一个结构体SmallDuck,它重写了String方法。具体的调用:

    1. type UglyDuckling interface{}
    2. func main() {
    3. var uglyDuckling UglyDuckling
    4. uglyDuckling = yellow.SmallDuck{Foot: 2}
    5. fmt.Printf("%T %v \n", uglyDuckling, uglyDuckling)
    6. }

    结果如下:

    yellow.SmallDuck foot is 2

    输出的SamllDuck的value为自定义的内容,即String方法返回的值

    Writer接口

    type Writer interface {   Write(p []byte) (n int, err error)}

    go语言的Writer接口定义了一个Write方法,当实现者为文件的时候,通过Write方法可以将byte数组里面内容write进入文件当中。

    Reader接口

    type Reader interface {   Read(p []byte) (n int, err error)}

    Reader接口定义了一个Read方法,当实现者为文件的时候,通过Read方法可以将文件里面的内容写进byte数组当中。除了文件实现了Reader接口和Writer接口外,byte数组,byte切片,网络流相关的也实现了Reader接口。因此,涉及到读写底层的东西,我们传入的是Writer和Reader接口,而不是File。例如fmt包的Fprintf方法和Fscanf方法

    1. func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
    2. p := newPrinter()
    3. p.doPrintf(format, a)
    4. n, err = w.Write(p.buf)
    5. p.free()
    6. return
    7. }
    8. func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) {
    9. s, old := newScanState(r, false, false)
    10. n, err = s.doScanf(format, a)
    11. s.free(old)
    12. return
    13. }

    具体的Reader操作例子。定义读取Reader里面内容的方法

    1. func printContents(reader io.Reader) {
    2. scanner := bufio.NewScanner(reader)
    3. for scanner.Scan() {
    4. fmt.Println(scanner.Text())
    5. }
    6. }

    具体调用

    1. func main() {
    2. s := `1 12!!!`
    3. printContents(strings.NewReader(s))
    4. }

    通过``定义一个跨行的字符串,通过string.NewReader()方法将s转为Reader类型,然后调用定义的方法,通过Scanner读取字符打印在控制台上。

    除了Reader和Writer外,还有组合它们的接口ReadWriter

    1. type ReadWriter interface {
    2. Reader
    3. Writer
    4. }

    实现者只要实现方法即可,具体的组合和调用由使用者决定。

  • 相关阅读:
    【Redis1】安装,操作,持久化,Jedis,数据库总结
    OpenCV中的形态学8
    uniapp实现时间选择器
    《Python3 网络爬虫开发实战》:便于高效检索的 Elasticsearch 存储
    C++学习规划“的 PPT 大纲设计
    print(torch.cuda.is_available()) False如何解决?GTX3090
    【无标题】
    自动化办公01 smtplib 邮件⾃动发送
    linux 的文件权限案列
    华为防火墙基础自学系列 | Site to Site IPSec VdPdNd
  • 原文地址:https://blog.csdn.net/hudeyong926/article/details/126359367