Go 语言接口及使用接口实现链表插入

首页 / 新闻资讯 / 正文

@

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

  • 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.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] 正在睡眠
  • 示例
    使用接口进行排序
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)     } }
  • 示例:
    文件读写测试
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) }   //输出结果如下 文件读取 文件写入
  • 作用:因为接口是一般类型,需要明确具体类型的时候就需要使用类型断言

示例

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 个数据类型是其他类型
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>}