V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Deardrops
V2EX  ›  Go 编程语言

学习疑惑: Golang 中接口的作用体现在哪里?

  •  
  •   Deardrops ·
    deardrops · 2018-09-28 16:56:46 +08:00 · 6483 次点击
    这是一个创建于 2256 天前的主题,其中的信息可能已经有所发展或是发生改变。

    初学 Golang,对于接口部分有一些不太理解的地方,希望 V 友能帮忙解答一下。

    package main
    
    import "fmt"
    
    type Stringer interface {
    	String() string
    }
    
    type Printer interface {
    	Stringer // 接口嵌入。
    	Print()
    }
    
    type User struct {
    	id   int
    	name string
    }
    
    func (self *User) String() string {
    	return fmt.Sprintf("user %d, %s", self.id, self.name)
    }
    
    func (self *User) Print() {
    	fmt.Println(self.String())
    }
    
    func main() {
    	var t Printer = &User{1, "Tom"} // *User 方法集包含 String、Print。
    	// 如果去掉接口定义的代码,将上一行代码替换为下行,也可以运行,请问接口的作用体现在哪里?
    	// var t := User{1, "Tom"}
    	t.Print()
    }
    

    以上代码摘录自Go 边看边练 -《 Go 学习笔记》系列(十二)

    书上写了接口声明一个方法的签名。声明一个空方法集的接口类型,并将其作为函数参数,函数不会检查传入的是什么类型,只要这个参数满足接口定义即可,即可以通过编译器检查(个人理解)。另外,接口可以进行接口检查,接口嵌入等。我学到了这些理论知识,但对接口缺乏感性的认识。

    相对于不定义接口,「直接定义结构体和结构体上的方法」的方式,额外定义了接口会带来什么好处么?

    可以举几个实际的例子么?

    11 条回复    2018-09-30 14:11:57 +08:00
    gowk
        1
    gowk  
       2018-09-28 17:12:15 +08:00   ❤️ 1
    接口跟语言无关,无非是为了抽象,具体说就是为了解耦,隔离变化。Go 语言中的接口跟 Java 中的大同小异,最大的区别就是 Go 语言的 Interface 是 Duck Typing,无侵入式的,另外我建议你不要用这个教程学习 Go 语言,教程里的例子为了举例而举例,对初学者而言完全没有任何意义。英文好的话直接看英文教程,推荐两本书,《 The Go Programming Language 》《 The Way To Go 》,英语对于程序员的重要性再怎么强调都不为过!
    gowk
        2
    gowk  
       2018-09-28 17:15:44 +08:00
    上面两本电子书找不到的话,可以访问我的百度网盘分享链接: https://pan.baidu.com/s/1mic0v00
    里面有很多经典的计算机类的 PDF 电子书
    imnotfine
        3
    imnotfine  
       2018-09-28 17:20:25 +08:00   ❤️ 2
    其实面向对象的问题.

    如果你初学编程的话, 我非常建议你跳过这部分, 因为需要你做一些项目才能理解其作用 ,特别是需要多人合作的项目

    ------

    举个栗子, 如果你写了一个类, 一年后你对这个类不满意, 你想重新实现一个, 那为了保证兼容性, 你肯定不能完全写个新的对吧.

    那你肯定要理清这个类提供了哪些公开的 api, 那你就得到了一个接口

    然后根据这些 api 去实现一个新的类, 然后用这个新的类去替换旧代码.

    -------

    下面是更好的方案

    那其实更好的方式是, 在刚开始写这个类的时候就想好这个类可以提供哪些方法, 然后定义一个接口, 然后一年后你写个新的, 你直接实现这个接口就好了, 而不用理清. 另外, 试想, 如果写这个新类的人是你同事, 让他去理清这些公开 api, 他应该会很头疼, 甚至直接放弃这个需求了吧.

    ------

    除了修改和重构上的方便外, 对调用方来说也是非常重要的, 这个涉及到多态, 然后你联想一下设计模式, 还有为什么允许`var t Printer = &User{1, "Tom"}`, 甚至推荐这种用法, 这就是你要思考的问题啦~
    Deardrops
        4
    Deardrops  
    OP
       2018-09-28 17:23:20 +08:00
    @gowk #1 感谢解答。正在看这两本书,看到接口的部分看不大明白,谷歌到的一个解释接口的文章,顺手贴出来了。书中说,Golang 语言中接口和满足接口的类型之间没有显式的连接,有时有的自定义类型可以同时满足多个接口,使用起来不会带来困惑么?
    neoblackcap
        5
    neoblackcap  
       2018-09-28 17:27:24 +08:00   ❤️ 2
    @Deardrops 这就是语言的哲学,也是面向对象的进一步理解。面向对象应该基于协议,接口。组合优先于继承,既然满足了接口,那么就应该认为这里的对象就是一类。
    Deardrops
        6
    Deardrops  
    OP
       2018-09-28 17:28:49 +08:00
    @imnotfine #3 感谢解答。之前写过一些 JS,对 OOP 一直没啥概念,听了你的解释明白了很多东西。谢谢!
    tourist2018
        7
    tourist2018  
       2018-09-28 17:38:15 +08:00
    golang 的接口就是一系列方法的集合
    misaka19000
        8
    misaka19000  
       2018-09-28 17:44:51 +08:00
    我也是在了解了 golang 的接口之后才对计算机里面的指令和数据有了更进一步的了解
    gamexg
        9
    gamexg  
       2018-09-28 20:58:03 +08:00   ❤️ 1
    实际使用下 go 的压缩、加密库就能够理解接口的作用了。
    加密、压缩传入 Writer 接口,输出的还是兼容 Writer,只要需求方实现了 Write 方法都能使用,不用管是文件还是连接。
    owenliang
        10
    owenliang  
       2018-09-29 09:52:39 +08:00
    面向接口编程啊,无论是过程式的还是对象式的,都可以实现接口和实现的分离。
    hijoker
        11
    hijoker  
       2018-09-30 14:11:57 +08:00
    感觉卵用没有,没有默认的接口实现
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2600 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 10:11 · PVG 18:11 · LAX 02:11 · JFK 05:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.