2023-11-10-接口

2023-11-09  本文已影响0人  护念

今日概述

今天主要学习go的接口

1. 结构体匿名字段

  1. 匿名字段既然省略了,默认和类型名相同(可以理解为派生出来的)
  2. 匿名字段是结构体时,此时发生提升:

PS: 如果遇到字段名称一样的有歧义,通过匿名字段中间层区分

看代码:

package main

import "fmt"

type Person struct {
    name string
    age  int
}

func (p *Person) hello() {
    fmt.Println("hello")
}

type Student struct {
    id     string
    Person // 匿名字段 相当于此时字段名也是Person
}

func main() {
    p := Student{
        id:     "001",
        Person: Person{name: "John", age: 12}, // 写时直接把字段写上
    }

    fmt.Println(p.id)
    fmt.Println(p.name) // 字段提升
    fmt.Println(p.age)  // 字段提升
    p.hello()           // 方法提升
}

2. 匿名字段 (是指针)

用法和上述一样,唯一需要记住的在于,初始化结构体时要传指针;

看代码:

package main

import "fmt"

type Person struct {
    name string
    age  int
}

func (p *Person) hello() {
    fmt.Println("hello")
}

type Student struct {
    id      string
    *Person // 初始化时候 要传指针
}

func main() {
    p := Student{
        id:     "001",
        Person: &Person{name: "John", age: 12}, // 初始化时候传指针
    }

    p.hello() // 方法提升
}

3. 什么是接口,有什么用?

概念:
接口相当于把不同的对象归类,具有同一类行为的我们称为同一个接口;比如,猪会叫、狗也会叫,鸭子也会叫,那么我们可以把叫这个行为动作抽象为一类接口;

有什么用?
go做为静态语言,它是强类型的;我们赋值给变量,这个变量都需要有一个类型,比如我们有一个猫 struct 还有一个 狗 struct 他们都实现了叫方法;我们定义变量时候需要给猫和狗定义不同的类型,才能赋值;

其实很麻烦,实现了接口后,我们可以不用区分猫还是狗,直接赋值给这个接口类型就行。

4. 接口中方法的接收者(值/指针)区别

  1. 值(随便调用) — 值/指针赋给接口类型都可
  2. 指针(严格) — 只能指针

一点小建议,

  1. 严格按照接收者去生成对象是个好习惯
  2. 在同一个结构体下方法,统一生成,要么是值接收者/要么是方法接收者

看代码

package main

import "fmt"

type Mover interface {
    move()
}

type Dog struct{}

// 值接收者 - 在接口中宽松
func (d Dog) move() {
    fmt.Println("dog move")
}

type Cat struct{}

// 指针接收者 - 严格
func (c *Cat) move() {
    fmt.Println("cat move")
}

func main() {
    var x Mover // 接口是一种类型

    // 值接收者 (啥都行)
    x = Dog{}
    x.move()
    x = &Cat{}
    x.move()

    // 指针接收者 严格
    x = &Cat{}
    x.move()

    // 不能这么用
    // x = Cat{} cannot use Cat{} (value of type Cat) as Mover value in assignment: Cat does not implement Mover (method move has pointer receiver)
    // x.move()
}

5. 接口嵌套

多个接口,可以组合生成一个新的接口;非常不错哦。

package main

import "fmt"

type Mover interface {
    move()
}

type Sayer interface {
    say()
}

type Animaler interface {
    Mover // 接口
    Sayer // 接口 此时合并了上述两个接口
}

// dog实现了Animaler接口
type Dog struct{}

func (d *Dog) move() {
    fmt.Println("dog move")
}

func (d *Dog) say() {
    fmt.Println("dog say")
}

func main() {
    var x Animaler = &Dog{} // 合并成一行写也不错哦
    x.say()
    x.move()
}

上一篇 下一篇

猜你喜欢

热点阅读