• Golang interface 接口的应用场景 使用细节


    接口应用场景


    对初学者讲,理解接口的概念不算太难,难的是不知道什么时候使用接口,下面我例举几个应用场景:

    1.说现在美国要制造轰炸机,武装直升机,专家只需把飞机需要的功能/规格定下来即可,然后让别的人具体实现就可。

    要去写一个结构体,结构体里面有些方法,这些方法让一个程序员去写肯定是不太好的,希望将每个人都动起来,可以找项目经理,项目经理去定义一个接口,大家去实现这个接口就完事了。这样就可以很好的控制管理项目的进度。

    其实也就是取定义规范,其他人将规范实现即可。

    你想要去排序,只需要取实现这个data接口就行了。 

    其实也就是传入实现了interface接口的方法全部实现的,那么就可以去调用包里面的sort方法,将这个类型传入进去即可。 

    sort包里面有一个Sort函数,sort里面接受data,它是一个接口,那么只要传进去的变量实现了接口Interface里面所有方法,传入进去,它自然就给你排序了。当你实现接口,那么Sort函数就会自动帮你实现排序。

    如果如下所示,之前使用email发送告警信息,后面如果要换成dingding去发送告警,那么代码就需要改动。 

    1. //如果产生了一个告警,将告警发送给相关的人
    2. //email sms weixin
    3. type EmailSender struct {
    4. }
    5. type DingDingSender struct {
    6. }
    7. func (e *EmailSender) Send(msg string) error {
    8. fmt.Println(msg)
    9. return nil
    10. }
    11. func (d *DingDingSender) Send(msg string) error{
    12. fmt.Println(msg)
    13. return nil
    14. }
    15. func test(e *EmailSender,msg string) {
    16. e.Send(msg)
    17. }
    18. func main() {
    19. sender := new(EmailSender)
    20. sender.Send("email send")
    21. }

    如果需要改动得修改如下,要将和email相关的代码全部修改,如果没有全部修改会导致编译的时候失败。

    为了解决这种问题,可以定义接口,这些结构体有个特点就是都有Send方法,这样就可以定义只有Send方法接口,那么参数类型就可以使用接口类型。

    如果定义了接口就方便多了,只需要改一个地方,也就是结构体实例化的地方即可

    1. type Sender interface {
    2. Send(string) error
    3. }
    4. sender := new(DingDingSender)
    5. test(sender,"dingding send")
    6. sender1 := new(EmailSender)
    7. test(sender1,"email send")

    2.说现在有一个项目经理,管理三个程序员,功能开发一个软件,为了控制和管理软件,项目经理可以定义一些接口,然后由程序员具体实现。

    项目经理只需要将接口定义好,剩下的让程序员a b c共同完成。这样就可以控制软件的开发进度。

    注意事项和细节


    1)接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)

    1. type interfaceA interface {
    2. Say()
    3. }
    4. type Student struct {
    5. }
    6. func (*Student) Say() {
    7. fmt.Println("I am a student")
    8. }
    9. func main() {
    10. var i interfaceA
    11. student := new(Student)
    12. i = student //结构体变量实现了接口的方法
    13. i.Say()
    14. }

    2)接口中所有的方法都没有方法体,即都是没有实现的方法。

    3)在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口。

    4)一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型。

    5)只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。

    1. type interfaceA interface {
    2. Say()
    3. }
    4. type integer int
    5. func (i *integer) Say() {
    6. fmt.Println("i地址为:", &i, "i的值为:", *i)
    7. }
    8. func main() {
    9. var i interfaceA
    10. var a integer = 5
    11. a.Say()
    12. }

    6)一个自定义类型可以实现多个接口

    7)Golang接口中不能有任何变量

    上面可以看到和传统的oop不一样,他是基于方法来实现的这个接口。而java这些它是显示实现的,必须显示的指定去实现哪个接口。而golang并不关心实现了哪个接口,只关心实现了哪个方法。

    8)一个接口(比如 A接口)可以继承多个别的接口(比如 B,C接口),这时如果要实现A接口也必须将B,C接口的方法也全部实现。

    可以看到A接口里面有两个方法,相当于将这两个接口继承下来了。那么就要将继承下来的接口里面的方法和本身的方法都去实现。

    9) interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil(在传入参数的时候,比如结构体,传入的不是值类型,传入的是引用类型,也就是&struct{}

    10)空接口interface没有任何方法,所以所有类型都实现了空接口(空接口其实就是一种数据类型,可以将任何的数据类型的变量赋值给空接口,如果参数是空接口的形参,那么意味着可以接受任何一种数据类型)

    下面可以看到结构体默认实现了空接口,其他类型也可以,字符串整型这些都是可以的。

    1. type T interface {
    2. }
    3. type student struct {
    4. age int
    5. name string
    6. }
    7. func main() {
    8. s := &student{
    9. age: 10,
    10. name: "lucas",
    11. }
    12. var t T = s
    13. fmt.Println(reflect.TypeOf(t))
    14. fmt.Println(t)
    15. var t3 interface{} = s
    16. fmt.Println(t3)
    17. }
    18. *main.student
    19. &{10 lucas}
    20. &{10 lucas}

    可以将任何的变量赋值给空接口

  • 相关阅读:
    hibernate ehcache.xml
    Java工程师面试题
    idea Plugins 搜索不到插件
    站外引流之道:跨境电商如何吸引更多流量?
    高数基础_函数的奇偶性
    Web前端、后端与建站:全方位解析四大基石、五大挑战、六大技术与七大策略
    技术类公司与业务类公司转型科技智能公司的异同
    VScode中使用svn常用简单操作
    第7/100天 阅读笔记
    notepad++堆缓冲区溢出漏洞CVE-2023-40031分析与复现
  • 原文地址:https://blog.csdn.net/qq_34556414/article/details/133605963