go语法专题:空接口,反射,空结构体,断言,泛型
参考:
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)
#第三定律 var x float64 = 3.4 v := reflect.ValueOf(x) #不可修改 v.SetFloat(7.1) // Error: will panic. var x float64 = 3.4 v := reflect.ValueOf(&x) #可修改 v.Elem().SetFloat(7.1) fmt.Println("x :", v.Elem().Interface())
空结构体
另外,有的时候你可能会看到空的结构体类型定义:
struct{}
表示没有任何属性和成员方法的空结构体,该类型的实例值只有一个,那就是 struct{}{},这个值在 Go 程序中永远只会存一份,并且占据的内存空间是 0,当我们在并发编程中,将通道(channel)作为传递简单信号的介质时,使用 struct{} 类型来声明最好不过。
断言
参考:http://c.biancheng.net/view/4281.html
在Go语言中类型断言的语法格式如下:
value, ok := x.(T)
其中,x 表示一个接口的类型,T 表示一个具体的类型(也可为接口类型)。
该断言表达式会返回 x 的值(也就是 value)和一个布尔值(也就是 ok),可根据该布尔值判断 x 是否为 T 类型:
- 如果 T 是具体某个类型,类型断言会检查 x 的动态类型是否等于具体类型 T。如果检查成功,类型断言返回的结果是 x 的动态值,其类型是 T。
- 如果 T 是接口类型,类型断言会检查 x 的动态类型是否满足 T。如果检查成功,x 的动态值不会被提取,返回值是一个类型为 T 的接口值。
- 无论 T 是什么类型,如果 x 是 nil 接口值,类型断言都会失败。
返回两个值
如果我们想知道类型断言是否失败,而不是失败时触发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 ... }
使用switch
func 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) } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?