1、GO学习之Hello World
2、GO学习之入门语法
3、GO学习之切片操作
4、GO学习之 Map 操作
5、GO学习之 结构体 操作
6、GO学习之 通道(Channel)
7、GO学习之 多线程(goroutine)
8、GO学习之 函数(Function)
9、GO学习之 接口(Interface)
按照公司目前的任务,go 学习是必经之路了,虽然行业卷,不过技多不压身,依旧努力!!!
在JAVA
中我们可以使用interface
来定义一个接口,抽离出来公共的字段和方法,再有不同的class
来实现这些接口和接口中方法,来实现代码的解耦和灵魂,主要依据的就是JAVA
的多态性,比如说在 Spring
框架中,有 EventListener
接口,然后实现了此接口的有好多class
(ContextRefreshListener、RestartListener…),每个实现类都有个子不同的功能。
那在 Go 语言中也有 interface
,我们可以通过 interface
来定义一种对象的行为规范,也就是定义了一组行为,不需要关注这些规范如何实现,我们可以通过接口将代码解耦,使得不同模块之间依赖减少,提高代码可维护性。
type {interfaceName} interface { MethodName(paramName paramType) returnType }
,比如:type Runner interface{ run(name string) string }
type Shape interface {Area() (float64, error)}
此例子中,定义了一个 Shape 的接口,这个接口提供了
Area
方法用来求图形的面积,分别定义矩形(Rectangle)和 圆形(Circle)两个结构体,并且实现了 Shape 中的 Area 方法,初始化矩形和圆形并且调用 Area 方法求出面积。
package main
import "fmt"
// 定义一个图形接口,方法是求图形的面积
type Shape interface {
Area() float64
}
// 定义一个矩形
type Rectangle struct {
Width float64
Height float64
}
// 矩形实现了 Shape 接口中求面积的 Area 方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// 定义一个圆形
type Circle struct {
Radius float64
}
// 圆形实现了 Shape 接口中求面积的 Area 方法
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
func main() {
// 定义一个接口类型变量
var shape Shape
// 创建一个矩形并赋值给接口 shape
shape = Rectangle{Width: 5, Height: 10}
fmt.Printf("矩形的面积是:%+v\n", shape.Area())
// 创建一个圆形并赋值给接口 shape
shape = Circle{Radius: 3}
fmt.Printf("圆形的面积是:%+v\n", shape.Area())
}
运行结果:
PS D:\workspaceGo\src\interface> go run .\interfaceTest.go
矩形的面积是:50
圆形的面积是:28.259999999999998
此例子中,定义了两个接口,分别是 ShapeArea(求面积) 和 ShapeRound(求周长) 两个接口,实例化了 Sequre 类型并且赋值给两个接口,调用各自接口方法
package main
import "fmt"
// 定义一个图形接口,方法是求图形的面积
type ShapeArea interface {
Area() float64
}
// 定一个图形接口,方法是求图形周长
type ShageRound interface {
Round() float64
}
// 定义一个正方形
type Sequre struct {
Side float64
}
// 正方形实现了 ShapeArea 接口中求面积的 Area 方法
func (s Sequre) Area() float64 {
return s.Side * s.Side
}
// 正方形实现了 ShapeRound 接口中周长 Round 的方法
func (s Sequre) Round() float64 {
return 4 * s.Side
}
func main() {
// 定义接口
var spaceArea ShapeArea
var spaceRound ShageRound
// 实例化 Sequre 结构体
s := Sequre{Side: 9}
// 赋值给接口 spaceArea 以求面积
spaceArea = s
fmt.Printf("正方形的面积是:%+v\n", spaceArea.Area())
// 赋值给接口 spaceRound 以求周长
spaceRound = s
fmt.Printf("正方形的周长是:%+v\n", spaceRound.Round())
}
运行结果:
PS D:\workspaceGo\src\interface> go run .\interfaceTest2.go
正方形的面积是:81
正方形的周长是:36
此示例中,定义了两个接口 Sayer 和 Mover ,为了方便其他类型是,又定义了一个接口 Animal 嵌套了 Sayer 和 Mover 两个接口,基于两个接口的规则一自身,然后定义了 Cat 结构体类型,实例化之后赋值给了 Animal 变量 ‘yuanbao’,元宝是之前养过的一只很有灵性的黑白猫,元宝就可以叫,还可以上蹿下跳了。
package main
import "fmt"
// 定义接口 表示可以说话
type Sayer interface {
say()
}
// 定义接口,表示可以移动
type Mover interface {
move()
}
// 接口嵌套
type Animal interface {
Sayer
Mover
}
// 定义结构体类型 猫咪
type Cat struct {
Name string
}
// 定义猫咪叫的方法
func (c Cat) say() {
fmt.Printf("喵咪 %+v 在叫'喵喵喵'\n", c.Name)
}
// 定义猫咪动的方法
func (c Cat) move() {
fmt.Printf("猫咪 %+v 在上蹿下跳\n", c.Name)
}
func main() {
var yuanbao Animal
yuanbao = Cat{Name: "元宝"}
yuanbao.say()
yuanbao.move()
}
运行结果:
PS D:\workspaceGo\src\interface> go run .\interfaceNested.go
喵咪 元宝 在叫'喵喵喵'
猫咪 元宝 在上蹿下跳
此示例中定义了一个空接口,既然接口是一种类型,不关心实现,那我们可以借助空接口来实现接受任何类型参数,类似于
JAVA
中的Object
超类,可以接受任何参数,可以作为函数的参数,也可以放在 map 中以便此 map 存放任何类型的值。
package main
import "fmt"
// 定义一个空接口
type Object interface{}
// 定义一个函数,接受任何类型参数
func show(o interface{}) {
fmt.Printf("type: %T, value: %+v\n", o, o)
}
func main() {
show(100)
show("phan日复一日,刻苦学习,成就大业!")
// 定义一个 Map, key为字符串,值为任何类型
var myInfo = make(map[string]interface{})
myInfo["name"] = "phen"
myInfo["age"] = 25
myInfo["hobby"] = "运动,看书,数钱"
myInfo["rich"] = false
fmt.Printf("phen的个人信息:%+v\n", myInfo)
}
运行结果:
PS D:\workspaceGo\src\interface> go run .\interfaceEmpty.go
type: int, value: 100
type: string, value: phan日复一日,刻苦学习,成就大业!
phen的个人信息:map[age:25 hobby:运动,看书,数钱 name:phen rich:false]
value, ok := x.(T)
,2、value := x.(T)
package main
import "fmt"
// 定义一个图形接口,方法是求图形的面积
type Shape interface {
Area() float64
}
// 定义一个矩形
type Rectangle struct {
Width float64
Height float64
}
// 矩形实现了 Shape 接口中求面积的 Area 方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func main() {
// 定义一个接口类型变量
var shape Shape
// 接口断言,如果 ok = true, 则 rect 的类型为 Rectangle
if rect, ok := shape.(Rectangle); ok {
fmt.Printf("矩形的面积为 %+v\n", rect.Area())
} else {
fmt.Println("接口 shape 不包含 Rectangle 的值")
}
// 创建一个矩形并赋值给接口 shape
shape = Rectangle{Width: 5, Height: 10}
// 接口断言,如果 ok2 = true, 则 r 的类型为 Rectangle
if r, ok2 := shape.(Rectangle); ok2 {
fmt.Printf("矩形的面积是:%+v\n", r.Area())
} else {
fmt.Println("接口 shape 不包含 Rectangle 的值")
}
}
运行结果:
PS D:\workspaceGo\src\interface> go run .\interfaceTest.go
接口 shape 不包含 Rectangle 的值
矩形的面积是:50
从运行结果看,在没有给接口 shape 赋值的时,断言 ok 是 false,下面给接口类型变量 shape 正式赋值了,则成功执行了 r.Area() 计算了面积。
接口类型在 Go 语言中是非常重要的特性,它提供了一种约定和抽象的方式,让不同的类型可以用相同的方式处理。在实际开发中有许多用途和场景,重要包括:
总而言之,接口类型在 Go 语言中非常灵活和强大,它可以帮助我们实现面向接口编程,提高代码的灵活性和可复用性,减少代码的耦合性,使得代码更加清晰、简洁和易于维护。在实际开发中,合理地使用接口类型,可以使代码更加健壮和可扩展,提高开发效率和质量。
现阶段还是对 Go 语言的学习阶段,想必有一些地方考虑的不全面,本文示例全部是亲自手敲代码并且执行通过。
如有问题,还请指教。
评论去告诉我哦!!!一起学习一起进步!!!