建设局特种作业网站,wordpress主题谁的最好,有哪些做设计交易网站有哪些,建设网站建设白度经验go 接口 interface 1、什么是接口#xff08;interface#xff09;#xff1f;2、注意事项3、interface底层实现4、侵入式与非侵入式5、接口的应用场景空接口的应用场景 6、其他使用 1、什么是接口#xff08;interface#xff09;#xff1f; 在Go语言中#xff0c;接口… go 接口 interface 1、什么是接口interface2、注意事项3、interface底层实现4、侵入式与非侵入式5、接口的应用场景空接口的应用场景 6、其他使用 1、什么是接口interface 在Go语言中接口interface是方法的集合它允许我们定义一组方法但不实现它们任何类型只要实现了这些方法就被认为是实现了该接口。 接口更重要的作用在于多态实现它允许程序以多态的方式处理不同类型的值。接口体现了程序设计的多态和高内聚、低耦合的思想。
package mainimport fmt// 定义接口
type Person interface {GetName() stringGetAge() int
}// 定义结构体
type Student struct {Name stringAge int
}// 实现接口
// 实现 GetName 方法
func (s Student) GetName() string {fmt.Println(name:, s.Name)return s.Name
}// 实现 GetAge 方法
func (s Student) GetAge() int {fmt.Println(age:, s.Age)return s.Age
}// 使用接口
func main() {var per Personvar stu Studentstu.Name xiaozhangstu.Age 24per stuper.GetName() // name: xiaozhangper.GetAge() // age: 24
}2、注意事项
1接口本身不能创建实例但是可以指向一个实现了该接口的自定义类型的变量实例。 2接口中所有的方法都没有方法体即都是没有实现的方法。 3在Go中一个自定义类型需要将某个接口的所有方法都实现才能说这个自定义类型实现了该接口。 4一个自定义类型只有实现了某个接口才能将该自定义类型的实例变量赋给接口类型。 5只要是自定义数据类型就可以实现接口不仅仅是结构体类型structs还包括类型别名type aliases、其他接口、自定义类型、变量等。 6一个自定义类型可以实现多个接口。 7interface 接口不能包含任何变量。 8一个接口可以继承多个别的接口这时如果要实现这个接口必须实现它继承的所有接口的方法。在低版本的Go编辑器中一个接口继承其他多个接口时不允许继承的接口有相同的方法名。比如A接口继承B、C接口B、C接口的方法名不能一样。高版本的Go编辑器没有相关问题。 9interface类型默认是一个指针引用类型如果没有对interface初始化就使用那么会输出nil。
var i interface{}
fmt.Println(i nil) // 输出true10在Go中接口的实现是非侵入式隐式的不需要显式声明“我实现了这个接口”。只要一个类型提供了接口中定义的所有方法的具体实现它就自动成为该接口的一个实现者。 11空接口interface{}没有任何方法是一个能装入任意数量、任意数据类型的数据容器我们可以把任何一个变量赋给空接口类型。任意数据类型都能实现空接口这就和 “空集能被任意集合包含” 一样空接口能被任意数据类型实现。
3、interface底层实现 Go的interface源码在Golang源码的runtime目录中。Go的interface是由两种类型来实现的iface和eface。runtime.iface表示非空接口类型runtime.eface表示空接口类型interface{}。 iface是包含方法的interface如
type Person interface {GetName()
} eface是不包含方法的interface即空interface如
type Person interface {
}
//或者
var person interface{} xxxx实体 iface的源代码是
type iface struct {tab *itab // 表示值的具体类型的类型描述符data unsafe.Pointer // 指向值的指针实际的数据
}itab是iface不同于eface的关键数据结构。其包含两部分一部分是唯一确定包含该interface的具体结构类型一部分是指向具体方法集的指针。
4、侵入式与非侵入式 GO语言的接口是非侵入式接口。
侵入式 侵入式接口的实现是显式声明的必须显式的表明我要继承那个接口必须通过特定的关键字如Java中的implements来声明实现关系。 优点通过侵入代码与你的代码结合可以更好的利用侵入代码提供给的功能。 缺点框架外代码就不能使用了不利于代码复用。依赖太多重构代码太痛苦了。 非侵入式 非侵入式接口的实现是隐式声明的不需要通过任何关键字声明类型与接口之间的实现关系。只要一个类型实现了接口的所有方法那么这个类型就实现了这个接口。 优点代码可复用方便移植。非侵入式也体现了代码的设计原则高内聚低耦合。 缺点无法复用框架提供的代码和功能。 侵入式接口存在的问题 1侵入式接口把实现类与具体接口绑定起来了强耦合; 2假如修改了接口方法则实现类方法必须改动 3假如类想再实现一个接口类方法也必须进行改动 4后续实现此接口的类必须了解相关的接口 Go语言非侵入式的方式很好地解决了这几个问题只要实现了与接口相同的方法就实现了这个接口。随着代码量的增加根本不需要关心实现了哪些接口不需要刻意去先定义接口再实现接口在原有类里新增实现接口时不需要更改类做到低侵入式、低耦合开发。 go语言中非侵入式接口的影响 1、go语言标准库不再需要绘制类库的继承树。 2、实现类的时候只需要关心自己应该提供哪些方法不用再纠结接口需要拆得多细才合理。 3、接口由使用方按自身需求来定义使用方无需关心是否有其他模块定义过类似的接口。 5、接口的应用场景 Go接口的应用场景包括多态性、解耦、扩展性、代码复用、API设计、单元测试、插件系统、依赖注入。 多态性接口使得代码可以更加灵活地处理不同类型的数据。通过接口可以编写更加通用的代码而无需关心具体的数据类型。 解耦通过接口将代码模块解耦降低模块之间的耦合度。不同模块只需要遵循同一个接口即可实现模块间的无缝整合。这样当一个模块的实现发生变化时其他模块不需要做出相应的修改。 扩展性通过接口可以轻松地为现有的类型添加新的功能只需实现相应的接口而无需修改原有的代码。这种方式使得代码更容易扩展和维护。 代码复用接口提供了一种将相似行为抽象出来并进行复用的方式从而减少了代码的重复性。这样可以更加高效地编写和维护代码。 API设计通过定义接口可以规范API的输入和输出提高代码的可读性和可维护性。 单元测试通过使用接口可以轻松地替换被测试对象的实现从而实现对被测代码的独立测试。 插件系统通过定义一组接口不同的插件可以实现这些接口并在程序运行时动态加载和使用插件。 依赖注入通过定义接口可以将依赖对象的创建和管理交给外部容器从而实现松耦合的代码结构。 类型转换。可将接口变量还原为原始类型或用来判断是否实现了某个更具体的接口类型。
var s int
var x interface
x s
y , ok : x.(int)
//将interface 转为int,ok可省略 但是省略以后转换失败会报错
//true转换成功false转换失败, 并采用默认值类型判断。用switch语句在多种类型间做出推断匹配这样空接口就有更多发挥空间。 var x interfaceswitch val.(type) {case nil: fmt.Println(nil) case string:fmt.Println(type is string, , val)case bool:fmt.Println(type is bool, , val)case int:fmt.Println(type is int, , val)case float32, float64:fmt.Println(type is float, , val)default: fmt.Println(unknown)
} 实现多态功能。根据对象的实际定义来实现不同的行为从而实现多态行为。
// 多态
package mainimport fmt// Shape 接口定义了一个计算面积的方法
type Shape interface {Area() float64
}// Rectangle 结构体实现了 Shape 接口
type Rectangle struct {Width, Height float64
}
func (r Rectangle) Area() float64 {return r.Width * r.Height
}// Circle 结构体实现了 Shape 接口
type Circle struct {Radius float64
}
func (c Circle) Area() float64 {return math.Pi * c.Radius * c.Radius
}// DescribeShape 接受 Shape 接口类型的参数输出图形的面积
func DescribeShape(s Shape) {fmt.Printf(Shape Area: %.2f\n, s.Area())
}func main() {r : Rectangle{Width: 3, Height: 4}c : Circle{Radius: 5}// 计算不同图形的面积DescribeShape(r) // Shape Area: 12.00DescribeShape(c) // Shape Area: 78.54
}作为函数参数或返回值。不推荐作为函数的返回值代码的维护、拓展与重构将会变得极为痛苦。
package mainimport fmtfunc GetType(val interface{}) {switch val.(type) {case nil: fmt.Println(nil) case string:fmt.Println(type is string, , val)case bool:fmt.Println(type is bool, , val)case int:fmt.Println(type is int, , val)case float32, float64:fmt.Println(type is float, , val)default: fmt.Println(unknown) }
}func main() {GetType(3) // type is int, 3GetType(interface) // type is string, interfaceGetType(3.01) // type is float, 3.01
}空接口的应用场景
1用空接口可以让函数和方法接受任意类型、任意数量的函数参数空接口切片还可以用于函数的可选参数。 2空接口还可以作为函数的返回值但是极不推荐这样干因为代码的维护、拓展与重构将会变得极为痛苦。 3空接口可以实现保存任意类型值的字典 (map)。
6、其他使用
interface接口嵌套
// 接口嵌套
package mainimport fmt// 定义接口
type Person interface {GetName() stringGetAge() int
}// 接口嵌套
type Test interface {GetSex() stringPerson // 继承Person
}type Student struct {Name stringAge int
}type Teacher struct {Name stringAge intSex string
}// 实现 GetName 方法
func (s Student) GetName() string {fmt.Println(name:, s.Name)return s.Name
}// 实现 GetAge 方法
func (s Student) GetAge() int {fmt.Println(age:, s.Age)return s.Age
}// 实现 GetName 方法
func (t Teacher) GetName() string {fmt.Println(name:, t.Name)return t.Name
}// 实现 GetAge 方法
func (t Teacher) GetAge() int {fmt.Println(age:, t.Age)return t.Age
}// 实现 GetSex 方法
func (t Teacher) GetSex() string {fmt.Println(sex:, t.Sex)return t.Sex
}func main() {var per Personvar stu Studentvar tea Teacherstu.Name xiaozhangstu.Age 24tea.Name lilaoshitea.Age 40tea.Sex manper stuper.GetName() // name: xiaozhangper.GetAge() // age: 24per teaper.GetName() // name: lilaoshiper.GetAge() // age: 40var test Testtest teatest.GetName() // name: lilaoshitest.GetAge() // age: 40test.GetSex() // sex: man
}interface 接口组合
// 接口的组合继承
package mainimport fmt// 可以闻
type Smellable interface {smell()
}
// 可以吃
type Eatable interface {eat()
}
// 接口组合
type Fruitable interface {SmellableEatable
}// 苹果既可能闻又能吃
type Apple struct{}func (a Apple) smell() {fmt.Println(apple can smell)
}func (a Apple) eat() {fmt.Println(apple can eat)
}// 花只可以闻
type Flower struct{}func (f Flower) smell() {fmt.Println(flower can smell)
}func main() {var s1 Smellablevar s2 Eatablevar apple Apple{}var flower Flower{}s1 apples1.smell() // apple can smells1 flowers1.smell() // flower can smells2 apples2.eat() // apple can eatvar s3 Fruitables3 apples3.smell() // apple can smells3.eat() // apple can eat
}