目录
  • 1. 接口定义
    • 1.1 空接口
    • 1.2 实现单一接口
    • 1.3 接口多方法实现
  • 2. 多态
    • 2.1 为不同数据类型的实体提供统一的接口
    • 2.2 多接口的实现
  • 3. 系统接口调用
    • 4. 接口嵌套
      • 5. 类型断言
        • 5.1 断言判断
        • 5.2 多类型判断
      • 6. 使用接口实现链表插入

        1. 接口定义

        • Interface 类型可以定义一组方法,不需要实现,并且不能包含任何的变量,称之为接口
        • 接口不需要显示的实现,只需要一个变量,含有接口类型中的所有方法,那么这个变量就实现了这个接口,如果一个变量含有多个interface 类型的方法,那么这个变量就实现了多个接口
        • 接口又称为动态数据类型,在进行接口使用的的时候,会将接口对位置的动态类型改为所指向的类型
        • 会将动态值改成所指向类型的结构体
        • 每个接口由数个方法组成,接口的定义格式如下:

        其中参数列表和返回值列表中的参数变量名可以省略

        type 接口类型名 interface{
            方法名1( 参数列表1 ) 返回值列表1
            方法名2( 参数列表2 ) 返回值列表2
            …
        }

        自定义接口步骤

        ① 定义接口

        ② 定义结构体

        ③ 接口实现(绑定结构体)

        ④ 定义接口变量,初始化结构体,调用接口实现功能

        1.1 空接口

        空接口就相当于一个空指针

        package main
        
        import "fmt"
        
        //定义空接口
        type Test interface{}
        
        func main() {
        	//声明接口方法1
        	var t Test
        	fmt.Printf("t的类型: %T, t的值: %v\n", t, t)
        	//声明接口方法2
        	var a interface{}
        	var b int
        	a = b
        	fmt.Printf("a的类型: %T, a的值: %v\n", a, a)
        }
        

        输出结果如下

        t的类型: <nil>, t的值: <nil>
        a的类型: int, a的值: 0

        1.2 实现单一接口

        结构体使用接口打印信息

        package main
        
        import "fmt"
        
        type Student struct {
        	Name  string
        	Age   int
        	Score float32
        }
        
        //接口定义:接口是功能的抽象,不需要实现
        type Test interface {
        	Print()
        }
        
        //指针类型实现接口
        func (p *Student) Print() {
        	fmt.Printf("name:[%s]\n", p.Name)
        	fmt.Printf("age:[%d]\n", p.Age)
        	fmt.Printf("score:[%f]\n", p.Score)
        }
        
        //值类型实现接口
        /*
        func (p Student) Print() {
        	fmt.Printf("name:[%s]\n", p.Name)
        	fmt.Printf("age:[%d]\n", p.Age)
        	fmt.Printf("score:[%f]\n", p.Score)
        }
        */
        
        func main() {
        	//声明接口变量
        	var t Test
        	//结构体初始化
        	var stu Student = Student{
        		Name:  "zhangsan",
        		Age:   18,
        		Score: 90,
        	}
        	//把结构体赋值给接口
        	t = &stu
        	//接口功能
        	t.Print()
        }
        

        输出结果如下

        name:[zhangsan]
        name:[18]
        name:[90.000000]

        1.3 接口多方法实现

        package main
        
        import "fmt"
        
        type Student struct {
        	Name  string
        	Age   int
        	Score float32
        }
        
        //接口定义:接口是功能的抽象,不需要实现
        type Test interface {
        	Print()
        	Sleep()
        }
        
        //接口的实现
        func (p *Student) Print() {
        	fmt.Printf("name:[%s]\n", p.Name)
        	fmt.Printf("age:[%d]\n", p.Age)
        	fmt.Printf("score:[%f]\n", p.Score)
        
        }
        
        //接口中包含多个方法,如果要使用此接口就要实现接口中包含的所有方法
        func (p *Student) Sleep() {
        	fmt.Println("正在睡眠~")
        }
        
        func main() {
        	//声明接口变量
        	var t Test
        	//结构体初始化
        	var stu Student = Student{
        		Name:  "zhangsan",
        		Age:   18,
        		Score: 90,
        	}
        	//把结构体赋值给接口
        	t = &stu
        	//接口功能
        	t.Print()
        	t.Sleep()
        }
        

        输出结果如下

        name:[zhangsan]
        name:[18]
        name:[90.000000]
        正在睡眠~

        示例,在电脑上定义一个USB接口,实现鼠标、U盘、风扇的功能

        package main
        
        import "fmt"
        
        //定义电脑
        type Computer struct {
        	Brand string	//品牌
        	Price float32	//价格
        }
        
        //定义USB接口
        type USB interface {
        	mouse()
        	store()
        	fan()
        }
        
        //接口功能实现
        func (c Computer) mouse() {
        	fmt.Println("鼠标")
        }
        
        func (c Computer) store() {
        	fmt.Println("U盘")
        }
        
        func (c Computer) fan() {
        	fmt.Println("风扇")
        }
        
        func main() {
        	//初始化结构体
        	var com Computer
        	//初始化接口
        	var usb USB
        	com.Brand = "thinkpad"
        	com.Price = 5000
        	//接口调用
        	usb = com
        	usb.mouse()
        	usb.fan()
        	usb.store()
        }
        

        输出结果如下

        鼠标
        风扇
        U盘

        2. 多态

        对于同一个接口,赋予给不同的结构体,使用相同的方法而产生出不同的操作,称之为多态。

        2.1 为不同数据类型的实体提供统一的接口

        package main
        
        import "fmt"
        
        //父结构体
        type Persion struct {
        	Name string
        	Age  int
        }
        
        //学生子结构体
        type Student struct {
        	Persion
        	Score float32
        }
        
        //教师子结构体
        type Teacher struct {
        	Persion
        	Class int
        }
        
        //接口定义:接口时功能的抽象,不需要实现
        type Test interface {
        	Print()
        	Sleep()
        }
        
        //学生结构体的实现
        func (p *Student) Print() {
        	fmt.Printf("name:[%s]\n", p.Name)
        	fmt.Printf("age:[%d]\n", p.Age)
        	fmt.Printf("Score:[%f]\n", p.Score)
        }
        
        //教师结构体的实现
        func (p *Teacher) Print() {
        	fmt.Printf("name:[%s]\n", p.Name)
        	fmt.Printf("age:[%d]\n", p.Age)
        	fmt.Printf("Class:[%d]\n", p.Class)
        
        }
        
        //接口中包含多个方法,如果要使用此接口就要实现接口中包含的所有方法
        func (p *Student) Sleep() {
        	fmt.Println("正在睡眠~")
        }
        
        func (p *Teacher) Sleep() {
        	fmt.Println("正在休息~")
        }
        
        func main() {
        	//声明接口变量
        	var t Test
        	//学生初始化
        	var stu Student
        	stu.Name = "zhangsan"
        	stu.Age = 18
        	stu.Score = 90
        
        	//教师初始化
        	var tea Teacher
        	tea.Name = "lisi"
        	tea.Age = 25
        	tea.Class = 3
        
        	//学生接口功能调用实现
        	t = &stu
        	t.Print()
        	t.Sleep()
        	fmt.Println("----------------------------")
        	//教师接口功能调用实现
        	t = &tea
        	t.Print()
        	t.Sleep()
        }
        

        输出结果如下

        name:[zhangsan]
        age:[18]
        Score:[90.000000]
        正在睡眠~
        —————————-
        name:[lisi]
        age:[25]
        Class:[3]
        正在休息~

        2.2 多接口的实现

        package main
        
        import "fmt"
        
        //接口1
        type Test1 interface {
        	Print()
        }
        
        //接口2
        type Test2 interface {
        	Sleep()
        }
        
        //结构体
        type Student struct {
        	Name  string
        	Age   int
        	Score float32
        }
        
        //接口1实现
        func (s Student) Print() {
        	fmt.Printf("name:[%s]\n", s.Name)
        }
        
        //接口2实现
        func (s Student) Sleep() {
        	fmt.Println("正在睡眠")
        }
        
        func main() {
        	//接口1变量
        	var t1 Test1
        	//接口2变量
        	var t2 Test2
        	//初始化结构体
        	var stu Student = Student{
        		Name:  "zhangsan",
        		Age:   18,
        		Score: 90,
        	}
        	//调用接口实现功能
        	t1 = stu
        	t1.Print()
        
        	t2 = stu
        	t2.Sleep()
        }

        输出结果如下

        name:[zhangsan]
        正在睡眠

        3. 系统接口调用

        示例

        使用接口进行排序

        package main
        
        import (
            "fmt"
            "math/rand"
            "sort"
        )
        
        //结构体
        type Student struct {
            Name  string
            Age   int
            Score float32
        }
        
        //切片
        type StudentArray []Student
        
        //go语言提供了sort 接口。使用接口里的方法即可
        //实现sort接口
        func (sa StudentArray) Len() int {
            return len(sa)
        } //获取切片长度
        func (sa StudentArray) Less(i, j int) bool {
            return sa[i].Name > sa[j].Name
        } //两数比大小
        func (sa StudentArray) Swap(i, j int) {
            sa[i], sa[j] = sa[j], sa[i]
        } //两数交换
        
        func main() {
            //Student 切片
            var stus StudentArray
        
            //生成10个结构体,放入切片中
            for i := 0; i < 10; i++ {
                var stu Student = Student{
                    Name:  fmt.Sprintf("stu%d", rand.Intn(100)),
                    Age:   rand.Intn(120),
                    Score: rand.Float32() * 100,
                }
        
                //结构体元素存入到切片中
                stus = append(stus, stu)
            }
        
            //遍历
            for _, v := range stus {
                fmt.Println(v)
            }
        
            fmt.Println("--------------------------")
            //排序
            sort.Sort(stus)
            //遍历
            for _, v := range stus {
                fmt.Println(v)
            }
        }
        

        4. 接口嵌套

        示例:

        文件读写测试

        package main
        
        import "fmt"
        
        //读取的接口
        type Reader interface {
        	Read()
        }
        
        //写入的接口
        type Writer interface {
        	Writer()
        }
        
        //接口的嵌套
        type ReadWriter interface {
        	Reader
        	Writer
        }
        
        //文件结构体
        type File struct{}
        
        //实现Reader接口
        func (f *File) Read() {
        	fmt.Println("文件读取")
        }
        
        //实现Writer接口
        func (f *File) Writer() {
        	fmt.Println("文件写入")
        }
        
        //定义读写操作函数
        func Test(rw ReadWriter) {  //rw为接口变量
        	rw.Read()				//使用读写的方法
        	rw.Writer()
        }
        
        func main() {
        	var f File				//定义结构体,初始化文件
        	Test(&f)
        }

        输出结果如下

        文件读取
        文件写入

        5. 类型断言

        作用:因为接口是一般类型,需要明确具体类型的时候就需要使用类型断言

        示例

        package main
        
        import "fmt"
        
        func main() {
        	//定义空接口
        	var a interface{}
        	var b int
        	a = b //a为int类型
        	//断言赋值
        	fmt.Printf("a= %v, 类型: %T\n", a, a)
        	c := a.(int)
        	fmt.Printf("c= %v, 类型: %T\n", c, c)
        }

        输出结果如下

        a= 0, 类型: int
        c= 0, 类型: int

        5.1 断言判断

        package main
        
        import "fmt"
        
        func main() {
        	//定义空接口
        	var a interface{}
        	var b string
        	a = b //a为int类型
        	//断言赋值
        	fmt.Printf("a= %v, 类型: %T\n", a, a)
        	c, err := a.(int)
        	if err {
        		fmt.Printf("c= %v, 类型: %T\n", c, c)
        	} else {
        		fmt.Println("不是int类型")
        	}
        }

        输出结果如下

        a= , 类型: string
        不是int类型

        package main
        
        import "fmt"
        
        func Test(t interface{}) {
        	//转换类型判断
        	v, err := t.(int)
        	if !err {
        		fmt.Println("type is not int")
        		return
        	}
        	v++
        	fmt.Println(v)
        }
        
        func main() {
        	a := "张三"
        	Test(a)
        }

        输出结果如下

        type is not int

        5.2 多类型判断

        package main
        
        import "fmt"
        
        func classifier(items ...interface{}) {
        	//遍历复杂集合
        	for i, v := range items {
        		//变量.(type)职能作用在switch语句中,专门用于判断类型
        		switch v.(type) {
        		case bool:
        			fmt.Printf("第 %d 个数据类型是 bool\n", i)
        		case int, int32, int64:
        			fmt.Printf("第 %d 个数据类型是 int\n", i)
        		case float32, float64:
        			fmt.Printf("第 %d 个数据类型是 float\n", i)
        		case string:
        			fmt.Printf("第 %d 个数据类型是 string\n", i)
        		default:
        			fmt.Printf("第 %d 个数据类型是其他类型\n", i)
        		}
        	}
        }
        
        func main() {
        	//传入多种类型参数
        	classifier("张三", 3.14, true, 80, nil)
        }
        

        输出结果如下

        第 0 个数据类型是 string
        第 1 个数据类型是 float
        第 2 个数据类型是 bool
        第 3 个数据类型是 int
        第 4 个数据类型是其他类型

        6. 使用接口实现链表插入

        package main
        
        import "fmt"
        
        //节点结构体
        type LinkNode struct {
            data interface{}
            next *LinkNode
        }
        
        //链表结构体
        type Link struct {
            head *LinkNode
            tail *LinkNode
        }
        
        //从头部插入
        func (p *Link) InsertHead(data interface{}) {
            node := &LinkNode{
                data: data,
                next: nil,
            }
            //判断是否为空链表
            if p.head == nil && p.tail == nil {
                p.head = node
                p.tail = node
                return
            }
            //当前节点的next是原头部节点
            node.next = p.head
            //更新头部
            p.head = node
        }
        
        //从尾部插入
        func (p *Link) InsertTail(data interface{}) {
            node := &LinkNode{
                data: data,
                next: nil,
            }
        
            //判断是否为空链表
            if p.head == nil && p.tail == nil {
                p.head = node
                p.tail = node
                return
            }
        
            //原尾部节点的next是当前节点
            p.tail.next = node
            //更新尾部
            p.tail = node
        }
        
        //遍历方法
        func (p *Link) Req() {
            lp := p.head
            for lp != nil {
                fmt.Println(lp)
                lp = lp.next
            }
        }
        
        func main() {
            //定义链表
            var intLink Link
            for i := 0; i < 10; i++ {
                //intLink.InsertHead(i)
                intLink.InsertTail(i)
            }
            intLink.Req()
        }

        输出结果如下

        &{0 0xc000096078}
        &{1 0xc000096090}
        &{2 0xc0000960a8}
        &{3 0xc0000960c0}
        &{4 0xc0000960d8}
        &{5 0xc0000960f0}
        &{6 0xc000096108}
        &{7 0xc000096120}
        &{8 0xc000096138}
        &{9 <nil>}

        声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。