在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
参考: https://blog.csdn.net/weixin_44014995/article/details/114596529(go语言的空接口,反射,泛型) https://www.jianshu.com/p/6a46fc7b6e5b(go语言的类型断言) 前言go语言就是通过接口interface{}和结构体struct{}组织起来的,interface{}是方法的集合,struct{}是数据结构的集合+接口的实现。 反射可以动态地获取任意对象的类型及其结构信息。 空接口的引入Go语言打破了传统面向对象编程中类与类之间继承的概念,而是通过组合实现方法和属性的复用,所以不存在类似的继承关系数,也就没有所谓的祖宗类,而且类与接口之间也不再通过implements 关键字强制绑定实现关系,所以 Go 语言的面向对象编程非常灵活。 在Go语言中,类与接口的实现关系是通过类所实现的方法在编译期推断出来的,如果我们定义一个空接口的话,那么显然所有的类都实现了这个接口,反过来,我们也可以通过空接口来指向任意类型,从而实现类似Java中Object类所承担的功能,而且显然Go的空接口实现更加简洁,通过一个简单的字面量即可完成: interface{}
空接口的基本使用指向任意类型变量#基本类型 var v1 interface{} = 1 // 将 int 类型赋值给 interface{} var v2 interface{} = "学院君" // 将 string 类型赋值给 interface{} var v3 interface{} = true // 将 bool 类型赋值给 interface{} #复合类型 var v4 interface{} = &v2 // 将指针类型赋值给 interface{} var v5 interface{} = []int{1, 2, 3} // 将切片类型赋值给 interface{} var v6 interface{} = struct{ // 将结构体类型赋值给 interface{} id int name string }{1, "学院君"} 声明任意类型的参数func Printf(fmt string, args ...interface{})
func Println(args ...interface{}) ...
func (p *pp) printArg(arg interface{}, verb rune)
反射反射三大定律:1,反射可以将interface变量转换成反射对象 2,反射可以将反射对象还原成interface变量 3,反射对象可修改,value值必须是可设置的 #第一定律 #TypeOf()和ValueOf()接受的参数都是interface{}类型的,也即x值是被转成了interface传入的。 var x float64 = 3.4 t := reflect.TypeOf(x) //t is reflext.Type fmt.Println("type:", t) v := reflect.ValueOf(x) //v is reflext.Value fmt.Println("value:", v) #第二定律 #对象x转换成反射对象v,v又通过Interface()接口转换成接口对象,interface对象通过.(float64)类型断言获取float64类型的值。 var y float64 = v.Interface().(float64) fmt.Println("value:", y)
空结构体另外,有的时候你可能会看到空的结构体类型定义: struct{} 表示没有任何属性和成员方法的空结构体,该类型的实例值只有一个,那就是 struct{}{},这个值在 Go 程序中永远只会存一份,并且占据的内存空间是 0,当我们在并发编程中,将通道(channel)作为传递简单信号的介质时,使用 struct{} 类型来声明最好不过。 断言golang中的所有程序都实现了interface{}的接口,这意味着,所有的类型如string,int,int64甚至是自定义的struct类型都就此拥有了interface{}的接口,这种做法和java中的Object类型比较类似。那么在一个数据通过func funcName(interface{})的方式传进来的时候,也就意味着这个参数被自动的转为interface{}的类型。 1,x.(T)检查x的动态类型是否是T,其中x必须是接口值。 2,如果接口是具体类型T,对接口值x断言其动态类型是具体类型T,若成功则提取出x的具体值(返回2个值的时候为具体值,true);如果检查失败则panic(返回2个值的时候为零值,false不会返回panic)。 3,无论T是什么类型,如果x是nil接口值,则类型断言失败。 4,如果x是空接口类型,则T没有要求;如果x是非空接口类型,则T必须是实现了x; 5,如果x是接口类型T,类型断言检查x的动态类型是否满足T,如果检查成功,x的动态值不会被提取,返回值是一个类型为T的接口值。 返回两个值如果我们想知道类型断言是否失败,而不是失败时触发panic,可以使用返回两个值的版本: y, ok := x.(T) #举例 var w io.Writer = os.Stdout f, ok := w.(*os.File) //成功:f为os.Stdout,ok为true b, ok := w.(*bytes.Buffer) //失败:b为零值,这里是nil, ok为false,no panic 惯用: if f, ok := w.(*os.File); ok { // ... use f ... } 使用switchfunc classifier(items ...interface{}) { for i, x := range items { switch x.(type) { case bool: fmt.Printf("Param #%d is a bool\n", i) case float64: fmt.Printf("Param #%d is a float64\n", i) case int, int64: fmt.Printf("Param #%d is a int\n", i) case nil: fmt.Printf("Param #%d is a nil\n", i) case string: fmt.Printf("Param #%d is a string\n", i) default: fmt.Printf("Param #%d is unknown\n", i) } } }
|
请发表评论