Go語(yǔ)言利用接口實(shí)現(xiàn)鏈表插入功能詳解
1. 接口定義
- Interface 類型可以定義一組方法,不需要實(shí)現(xiàn),并且不能包含任何的變量,稱之為接口
- 接口不需要顯示的實(shí)現(xiàn),只需要一個(gè)變量,含有接口類型中的所有方法,那么這個(gè)變量就實(shí)現(xiàn)了這個(gè)接口,如果一個(gè)變量含有多個(gè)interface 類型的方法,那么這個(gè)變量就實(shí)現(xiàn)了多個(gè)接口
- 接口又稱為動(dòng)態(tài)數(shù)據(jù)類型,在進(jìn)行接口使用的的時(shí)候,會(huì)將接口對(duì)位置的動(dòng)態(tài)類型改為所指向的類型
- 會(huì)將動(dòng)態(tài)值改成所指向類型的結(jié)構(gòu)體
- 每個(gè)接口由數(shù)個(gè)方法組成,接口的定義格式如下:
其中參數(shù)列表和返回值列表中的參數(shù)變量名可以省略
type 接口類型名 interface{
方法名1( 參數(shù)列表1 ) 返回值列表1
方法名2( 參數(shù)列表2 ) 返回值列表2
…
}
自定義接口步驟
① 定義接口
② 定義結(jié)構(gòu)體
③ 接口實(shí)現(xiàn)(綁定結(jié)構(gòu)體)
④ 定義接口變量,初始化結(jié)構(gòu)體,調(diào)用接口實(shí)現(xiàn)功能
1.1 空接口
空接口就相當(dāng)于一個(gè)空指針
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)
}
輸出結(jié)果如下
t的類型: <nil>, t的值: <nil>
a的類型: int, a的值: 0
1.2 實(shí)現(xiàn)單一接口
結(jié)構(gòu)體使用接口打印信息
package main
import "fmt"
type Student struct {
Name string
Age int
Score float32
}
//接口定義:接口是功能的抽象,不需要實(shí)現(xiàn)
type Test interface {
Print()
}
//指針類型實(shí)現(xiàn)接口
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)
}
//值類型實(shí)現(xiàn)接口
/*
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
//結(jié)構(gòu)體初始化
var stu Student = Student{
Name: "zhangsan",
Age: 18,
Score: 90,
}
//把結(jié)構(gòu)體賦值給接口
t = &stu
//接口功能
t.Print()
}
輸出結(jié)果如下
name:[zhangsan]
name:[18]
name:[90.000000]
1.3 接口多方法實(shí)現(xiàn)
package main
import "fmt"
type Student struct {
Name string
Age int
Score float32
}
//接口定義:接口是功能的抽象,不需要實(shí)現(xiàn)
type Test interface {
Print()
Sleep()
}
//接口的實(shí)現(xiàn)
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)
}
//接口中包含多個(gè)方法,如果要使用此接口就要實(shí)現(xiàn)接口中包含的所有方法
func (p *Student) Sleep() {
fmt.Println("正在睡眠~")
}
func main() {
//聲明接口變量
var t Test
//結(jié)構(gòu)體初始化
var stu Student = Student{
Name: "zhangsan",
Age: 18,
Score: 90,
}
//把結(jié)構(gòu)體賦值給接口
t = &stu
//接口功能
t.Print()
t.Sleep()
}
輸出結(jié)果如下
name:[zhangsan]
name:[18]
name:[90.000000]
正在睡眠~
示例,在電腦上定義一個(gè)USB接口,實(shí)現(xiàn)鼠標(biāo)、U盤、風(fēng)扇的功能
package main
import "fmt"
//定義電腦
type Computer struct {
Brand string //品牌
Price float32 //價(jià)格
}
//定義USB接口
type USB interface {
mouse()
store()
fan()
}
//接口功能實(shí)現(xiàn)
func (c Computer) mouse() {
fmt.Println("鼠標(biāo)")
}
func (c Computer) store() {
fmt.Println("U盤")
}
func (c Computer) fan() {
fmt.Println("風(fēng)扇")
}
func main() {
//初始化結(jié)構(gòu)體
var com Computer
//初始化接口
var usb USB
com.Brand = "thinkpad"
com.Price = 5000
//接口調(diào)用
usb = com
usb.mouse()
usb.fan()
usb.store()
}
輸出結(jié)果如下
鼠標(biāo)
風(fēng)扇
U盤
2. 多態(tài)
對(duì)于同一個(gè)接口,賦予給不同的結(jié)構(gòu)體,使用相同的方法而產(chǎn)生出不同的操作,稱之為多態(tài)。
2.1 為不同數(shù)據(jù)類型的實(shí)體提供統(tǒng)一的接口
package main
import "fmt"
//父結(jié)構(gòu)體
type Persion struct {
Name string
Age int
}
//學(xué)生子結(jié)構(gòu)體
type Student struct {
Persion
Score float32
}
//教師子結(jié)構(gòu)體
type Teacher struct {
Persion
Class int
}
//接口定義:接口時(shí)功能的抽象,不需要實(shí)現(xiàn)
type Test interface {
Print()
Sleep()
}
//學(xué)生結(jié)構(gòu)體的實(shí)現(xiàn)
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)
}
//教師結(jié)構(gòu)體的實(shí)現(xiàn)
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)
}
//接口中包含多個(gè)方法,如果要使用此接口就要實(shí)現(xiàn)接口中包含的所有方法
func (p *Student) Sleep() {
fmt.Println("正在睡眠~")
}
func (p *Teacher) Sleep() {
fmt.Println("正在休息~")
}
func main() {
//聲明接口變量
var t Test
//學(xué)生初始化
var stu Student
stu.Name = "zhangsan"
stu.Age = 18
stu.Score = 90
//教師初始化
var tea Teacher
tea.Name = "lisi"
tea.Age = 25
tea.Class = 3
//學(xué)生接口功能調(diào)用實(shí)現(xiàn)
t = &stu
t.Print()
t.Sleep()
fmt.Println("----------------------------")
//教師接口功能調(diào)用實(shí)現(xiàn)
t = &tea
t.Print()
t.Sleep()
}
輸出結(jié)果如下
name:[zhangsan]
age:[18]
Score:[90.000000]
正在睡眠~
----------------------------
name:[lisi]
age:[25]
Class:[3]
正在休息~
2.2 多接口的實(shí)現(xiàn)
package main
import "fmt"
//接口1
type Test1 interface {
Print()
}
//接口2
type Test2 interface {
Sleep()
}
//結(jié)構(gòu)體
type Student struct {
Name string
Age int
Score float32
}
//接口1實(shí)現(xiàn)
func (s Student) Print() {
fmt.Printf("name:[%s]\n", s.Name)
}
//接口2實(shí)現(xiàn)
func (s Student) Sleep() {
fmt.Println("正在睡眠")
}
func main() {
//接口1變量
var t1 Test1
//接口2變量
var t2 Test2
//初始化結(jié)構(gòu)體
var stu Student = Student{
Name: "zhangsan",
Age: 18,
Score: 90,
}
//調(diào)用接口實(shí)現(xiàn)功能
t1 = stu
t1.Print()
t2 = stu
t2.Sleep()
}輸出結(jié)果如下
name:[zhangsan]
正在睡眠
3. 系統(tǒng)接口調(diào)用
示例
使用接口進(jìn)行排序
package main
import (
"fmt"
"math/rand"
"sort"
)
//結(jié)構(gòu)體
type Student struct {
Name string
Age int
Score float32
}
//切片
type StudentArray []Student
//go語(yǔ)言提供了sort 接口。使用接口里的方法即可
//實(shí)現(xiàn)sort接口
func (sa StudentArray) Len() int {
return len(sa)
} //獲取切片長(zhǎng)度
func (sa StudentArray) Less(i, j int) bool {
return sa[i].Name > sa[j].Name
} //兩數(shù)比大小
func (sa StudentArray) Swap(i, j int) {
sa[i], sa[j] = sa[j], sa[i]
} //兩數(shù)交換
func main() {
//Student 切片
var stus StudentArray
//生成10個(gè)結(jié)構(gòu)體,放入切片中
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,
}
//結(jié)構(gòu)體元素存入到切片中
stus = append(stus, stu)
}
//遍歷
for _, v := range stus {
fmt.Println(v)
}
fmt.Println("--------------------------")
//排序
sort.Sort(stus)
//遍歷
for _, v := range stus {
fmt.Println(v)
}
}
4. 接口嵌套
示例:
文件讀寫測(cè)試
package main
import "fmt"
//讀取的接口
type Reader interface {
Read()
}
//寫入的接口
type Writer interface {
Writer()
}
//接口的嵌套
type ReadWriter interface {
Reader
Writer
}
//文件結(jié)構(gòu)體
type File struct{}
//實(shí)現(xiàn)Reader接口
func (f *File) Read() {
fmt.Println("文件讀取")
}
//實(shí)現(xiàn)Writer接口
func (f *File) Writer() {
fmt.Println("文件寫入")
}
//定義讀寫操作函數(shù)
func Test(rw ReadWriter) { //rw為接口變量
rw.Read() //使用讀寫的方法
rw.Writer()
}
func main() {
var f File //定義結(jié)構(gòu)體,初始化文件
Test(&f)
}輸出結(jié)果如下
文件讀取
文件寫入
5. 類型斷言
作用:因?yàn)榻涌谑且话泐愋?,需要明確具體類型的時(shí)候就需要使用類型斷言
示例
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)
}輸出結(jié)果如下
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類型")
}
}輸出結(jié)果如下
a= , 類型: string
不是int類型
package main
import "fmt"
func Test(t interface{}) {
//轉(zhuǎn)換類型判斷
v, err := t.(int)
if !err {
fmt.Println("type is not int")
return
}
v++
fmt.Println(v)
}
func main() {
a := "張三"
Test(a)
}輸出結(jié)果如下
type is not int
5.2 多類型判斷
package main
import "fmt"
func classifier(items ...interface{}) {
//遍歷復(fù)雜集合
for i, v := range items {
//變量.(type)職能作用在switch語(yǔ)句中,專門用于判斷類型
switch v.(type) {
case bool:
fmt.Printf("第 %d 個(gè)數(shù)據(jù)類型是 bool\n", i)
case int, int32, int64:
fmt.Printf("第 %d 個(gè)數(shù)據(jù)類型是 int\n", i)
case float32, float64:
fmt.Printf("第 %d 個(gè)數(shù)據(jù)類型是 float\n", i)
case string:
fmt.Printf("第 %d 個(gè)數(shù)據(jù)類型是 string\n", i)
default:
fmt.Printf("第 %d 個(gè)數(shù)據(jù)類型是其他類型\n", i)
}
}
}
func main() {
//傳入多種類型參數(shù)
classifier("張三", 3.14, true, 80, nil)
}
輸出結(jié)果如下
第 0 個(gè)數(shù)據(jù)類型是 string
第 1 個(gè)數(shù)據(jù)類型是 float
第 2 個(gè)數(shù)據(jù)類型是 bool
第 3 個(gè)數(shù)據(jù)類型是 int
第 4 個(gè)數(shù)據(jù)類型是其他類型
6. 使用接口實(shí)現(xiàn)鏈表插入
package main
import "fmt"
//節(jié)點(diǎn)結(jié)構(gòu)體
type LinkNode struct {
data interface{}
next *LinkNode
}
//鏈表結(jié)構(gòu)體
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
}
//當(dāng)前節(jié)點(diǎn)的next是原頭部節(jié)點(diǎn)
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
}
//原尾部節(jié)點(diǎn)的next是當(dāng)前節(jié)點(diǎn)
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()
}輸出結(jié)果如下
&{0 0xc000096078}
&{1 0xc000096090}
&{2 0xc0000960a8}
&{3 0xc0000960c0}
&{4 0xc0000960d8}
&{5 0xc0000960f0}
&{6 0xc000096108}
&{7 0xc000096120}
&{8 0xc000096138}
&{9 <nil>}
到此這篇關(guān)于Go語(yǔ)言利用接口實(shí)現(xiàn)鏈表插入功能詳解的文章就介紹到這了,更多相關(guān)Go語(yǔ)言接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang使用Gin框架實(shí)現(xiàn)路由分類處理請(qǐng)求流程詳解
Gin是一個(gè)golang的微框架,封裝比較優(yōu)雅,具有快速靈活,容錯(cuò)方便等特點(diǎn),這篇文章主要介紹了Golang使用Gin框架實(shí)現(xiàn)路由分類處理請(qǐng)求,感興趣的同學(xué)可以參考下文2023-05-05
GoFrame錯(cuò)誤處理常用方法及錯(cuò)誤碼使用示例
這篇文章主要為大家介紹了GoFrame錯(cuò)誤處理常用方法及錯(cuò)誤碼使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Go語(yǔ)言中關(guān)于set的實(shí)現(xiàn)思考分析
Go?開發(fā)過程中有時(shí)我們需要集合(set)這種容器,但?Go?本身未內(nèi)置這種數(shù)據(jù)容器,故常常我們需要自己實(shí)現(xiàn),下面我們就來看看具體有哪些實(shí)現(xiàn)方法吧2024-01-01
Go語(yǔ)言metrics應(yīng)用監(jiān)控指標(biāo)基本使用說明
這篇文章主要為大家介紹了Go語(yǔ)言metrics應(yīng)用監(jiān)控指標(biāo)的基本使用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02

