接口
程序员文章站
2022-07-14 10:48:24
...
Go接口
为什么要使用接口?
使用接口,好处在于简单又规范、易于维护和拓展、安全且严密。
使用接口,能解耦合,什么是耦合?指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象,解耦就是用数学方法将两种运动分离开来处理问题。通俗一点来说耦合就是程序之间的关联性,而解耦就是将程序之间的关联性降得越低越好,修改一部分代码时,其他的地方受到的影响越小。
接口就是将功能定义与功能实现相分离,降低模块之间的耦合度,以至于一个模块出现问题,不会影响其他模块。
如何定义接口
type 接口类型名 interface{
方法名1(参数列表)[返回值列表1]
方法名2(参数列表)[返回值列表2]
...
}
//
1.类型接口名:一般在单词后面加er,如speaker,Writer,Stringer
2.方法名:当方法名的首字母是大写&&接口类项名首字母大写,方法可被接口所在包之外的代码访问
3.参数列表:参数列表和返回值列表中的参数变量名可以忽略,如
type writer interface{
Write([] byte) error
}
/*定义接口*/
type interface_name interface{
method_name [return_type]
method_name [return_type]
method_name [return_type]
}
/*定义结构体*/
type struct_name struct{
/*variables*/
}
/*实现接口方法*/
func(struct_name_variable struct_name) method_name() [return_type]{
/*方法实现*/
}
...
func(struct_name_variable struct_name) method_name() [return_type]{
/*方法实现*/
}
关于接口定义的栗子
golang中接口使用类似于Java中的定义接口、定义类继承接口并且实现接口方法、创建对象并实例化对象、调用对象的成员属性和成员方法
//1.定义接口
type USB interface {
start()
end()
}
//2.实现类
type Mouse struct {
name string
}
type FlashDisk struct {
name string
}
//3.实现接口方法
func (m Mouse)start(){
fmt.Println(m.name,"鼠标,开始工作,点")
}
func (m Mouse)end(){
fmt.Println(m.name,"鼠标,结束工作")
}
func (f FlashDisk)start(){
fmt.Println(f.name,"准备工作,可进行数据存储")
}
func (f FlashDisk)end(){
fmt.Println(f.name,"结束,可弹出")
}
//4.测试方法
func TestInterface(usb USB) {
usb.start()
usb.end()
}
func main() {
//1.创建Mouse类型结构体
m1 := Mouse{"monkey1-m1"}
fmt.Println(m1.name)
//2.创建FlashDisk类型结构体
f1 := FlashDisk{"monkey2-f1"}
fmt.Println(f1.name)
//3.调用函数
TestInterface(m1)
TestInterface(f1)
/**
注意!!!下面!!!
*/
/**
var usb USB
usb = m1
usb.start() //能输出m1的start()
usb.end() //能输出m1的end()
fmt.Println(usb.name)//这里报错,usb不能访问m1的成员属性
*/
}
如何实现值和指针接收、接口嵌套?
定义嵌套接口 - - 这里可以将接口嵌套理解为Java中的继承
//接口嵌套
type Animal interface {
mover
eater
}
type mover interface{
move()
}
type eater interface {
eat(string)
}
//实现类
type cat struct {
name string
age int
}
值接收实现接口
//cat对象实现接口功能
func (c cat) eat(food string){
fmt.Println("猫吃")
//fmt.Printf("%s吃%s\n",c.name,food)
}
func (c cat) move(){
fmt.Println("猫跑")
//fmt.Printf("%s跑步",c.name)
}
func main() {
var a Animal
c1 := &cat{"猫",10} //c1为*cat类型
a = c1 //a可以接收*cat类型的
c2 := cat{"猫猫",12} //c2为cat类型
a = c2 //a可以接收cat类型的
}
指针接收实现接口
//cat对象实现接口功能
func (c *cat) eat(food string){
fmt.Println("猫吃")
//fmt.Printf("%s吃%s\n",c.name,food)
}
func (c *cat) move(){
fmt.Println("猫跑")
//fmt.Printf("%s跑步",c.name)
}
func main() {
var a Animal
c1 := &cat{"猫",10} //c1是*cat类型的
a = c1 //a可以接收*cat类型的
//若下面不加取地址符,报错
c2 := cat{"猫猫",12} //c2是cat类型的
a = c2 //这里报错,a不能接收cat类型的
}
空接口拿来做什么?
定义空接口
空接口没有定义任何方法,任何类型实现空接口
//定义空接口a
var A interface{}
var a1 A = Person("monkey",20)
var a2 A = "monkey"
var a3 A =100
空接口中没有定义任何方法,故所有的类型都实现了空接口,空接口类型的变量可以存储任意类型的变量。
空接口实现接收任意类型的函数参数
.....//该函数可接收任意类型的函数参数
func MyFunc(a interface{}){
}
空接口作为map的值,保存任意值的字典
var m1 map[string]interface{}
m1 = make(map[string]interface{},16)
m1["name"] = "monkey"
m1["age"] = 10
m1["married"] = false
m1["height"] = 163.5
m1["hobby"] = [...]string{"上网","学习","追剧"}
fmt.Println(m1)
//map[age:10 height:163.5 hobby:[上网 学习 追剧] married:false name:monkey]
类型断言:判断空接口中的值类型
i.(Type)
//
1.i表示类型为interface{}的变量
2.Type表示断言i可能是的类型
3.返回值:2个
返回值1---i转化为Type类型后的变量
返回值2---布尔值,判断断言是否成功
验证空接口和类型断言
func show(i interface{}){
fmt.Printf("Type:%T Value:%v \n",i,i)
}
func assign(i interface{}){
fmt.Printf("传进来的是 %T 类型\n",i)
//若传进来是除string外的其他类型
//会返回错误
str,ok:= i.(string)//判断类型
if !ok{
fmt.Println("传进来的不是string类型")
}else {
fmt.Println("传进来的就是string类型",str)
}
fmt.Printf("%T \n",str)
}
func main() {
show(false) //bool
show(nil) //<nil>
show(10.5) //float64
show(10) //int
show([...]string{"上网","学习"}) //[2]string
show("monkey") //string
assign(152) //int,传进去之后将int型数据转化为string类型的变量 i.(string)
}
判断断言多次使用switch-case结构完成
func justfyType(i interface{}){
switch i.(type) {
case string:
fmt.Println("string类型",i.(string))
case int:
fmt.Println("int类型",i.(int))
case float64:
fmt.Println("float64类型",i.(float64))
case bool:
fmt.Println("布尔类型",i.(bool))
}
}
func main() {
justfyType(100)
justfyType("monkey")
justfyType(10.4)
justfyType(true)
}