golang获取变量数据类型
如果某个函数的入参是interface{},有下面几种方式可以获取入参的方法:
1 fmt:
import "fmt"
func main() {
v := "hello world"
fmt.Println(typeof(v))
}
func typeof(v interface{}) string {
return fmt.Sprintf("%T", v)
}
2 反射:
import (
"reflect"
"fmt"
)
func main() {
v := "hello world"
fmt.Println(typeof(v))
}
func typeof(v interface{}) string {
return reflect.TypeOf(v).String()
}
3 类型断言:
func main() {
v := "hello world"
fmt.Println(typeof(v))
}
func typeof(v interface{}) string {
switch t := v.(type) {
case int:
return "int"
case float64:
return "float64"
//... etc
default:
_ = t
return "unknown"
}
}
其实前两个都是用了反射,fmt.Printf(“%T”)里最终调用的还是reflect.TypeOf()。
func (p *pp) printArg(arg interface{}, verb rune) {
...
// Special processing considerations.
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
p.fmt.fmt_s(reflect.TypeOf(arg).String())
return
case 'p':
p.fmtPointer(reflect.ValueOf(arg), 'p')
return
}
reflect.TypeOf()的参数是v interface{},golang的反射是怎么做到的呢?
在golang中,interface也是一个结构体,记录了2个指针:
- 指针1,指向该变量的类型
- 指针2,指向该变量的value
如下,空接口的结构体就是上述2个指针,第一个指针的类型是type rtype struct;非空接口由于需要携带的信息更多(例如该接口实现了哪些方法),所以第一个指针的类型是itab,在itab中记录了该变量的动态类型: typ *rtype。
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ *rtype
word unsafe.Pointer
}
// nonEmptyInterface is the header for a interface value with methods.
type nonEmptyInterface struct {
// see ../runtime/iface.go:/Itab
itab *struct {
ityp *rtype // static interface type
typ *rtype // dynamic concrete type
link unsafe.Pointer
bad int32
unused int32
fun []unsafe.Pointer // method table
}
word unsafe.Pointer
}
我们来看看reflect.TypeOf():
// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i interface{}) Type {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
}
TypeOf看到的是空接口interface{},它将变量的地址转换为空接口,然后将将得到的rtype转为Type接口返回。需要注意,当调用reflect.TypeOf的之前,已经发生了一次隐式的类型转换,即将具体类型的向空接口转换。这个过程比较简单,只要拷贝typ *rtype和word unsafe.Pointer就可以了。
例如w := os.Stdout,该变量的接口值在内存里是这样的:

那么对于第三种,类型断言是怎么判断是不是某个接口呢?回到最初,在golang中,接口是一个松耦合的概念,一个类型是不是实现了某个接口,就是看该类型是否实现了该接口要求的所有函数,所以,类型断言判断的方法就是检查该类型是否实现了接口要求的所有函数。
走读k8s代码的时候,可以看到比较多的类型断言的用法:
func LeastRequestedPriorityMap(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) {
var nonZeroRequest *schedulercache.Resource
if priorityMeta, ok := meta.(*priorityMetadata); ok {
nonZeroRequest = priorityMeta.nonZeroRequest
} else {
// We couldn't parse metadata - fallback to computing it.
nonZeroRequest = getNonZeroRequests(pod)
}
return calculateUnusedPriority(pod, nonZeroRequest, nodeInfo)
}
类型断言的实现在src/runtime/iface.go里(?),不过这块代码没看懂,等以后再更新吧。
func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) {
tab := i.tab
if tab == nil {
return
}
if tab.inter != inter {
tab = getitab(inter, tab._type, true)
if tab == nil {
return
}
}
r.tab = tab
r.data = i.data
b = true
return
}
func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) {
t := e._type
if t == nil {
return
}
tab := getitab(inter, t, true)
if tab == nil {
return
}
r.tab = tab
r.data = e.data
b = true
return
}
查看原文地址
golang获取变量数据类型的更多相关文章
- golang 获取变量类型的字符串格式 列举变量类型
fmt.Println(reflect.TypeOf(var)) switch xxx.(type){ case int:.... case float32:... case float64:... ...
- Go-获取变量数据类型
package main import ( "fmt" "reflect" //这个包里的TypeOf方法获取变量数据类型 ) func main(){ b : ...
- JS魔法堂:函数重载 之 获取变量的数据类型
Brief 有时我们需要根据入参的数据类型来决定调用哪个函数实现,就是说所谓的函数重载(function overloading).因为JS没有内置函数重载的特性,正好给机会我们思考和实现一套这样的机 ...
- typeof获取变量的数据类型 javascript
获取变量的数据类型:typeof <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- Java知识日常收集整理001Java获取变量的数据类型的实现方法
一.具体情况区分 对于简单类型变量,是无法直接获得变量类型的:要想获取,必须自定义函数进行返回. 对于包装类型变量,是可以直接获得的,变量名称.getClass().getName(); 二.代码实现 ...
- golang之基本数据类型
目录 一.golang之基本数据类型 1. 整型 (1)有符号(范围是负数.0和正数) (2)无符号(范围是0和正数) (3)特殊整型 (4)数字字面量语法 2. 浮点型 3. 复数类型 4. 布尔类 ...
- Golang的基础数据类型-浮点型
Golang的基础数据类型-浮点型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.浮点型概述 Go语言提供两种精度的浮点数,即float32和float64,其中float32 ...
- Golang的变量定义及使用案例
Golang的变量定义及使用案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.变量的定义 package main import "fmt" func m ...
- Learn day1 变量/数据类型
1.Python 简介 (1) 1989年开发的语言,创始人范罗苏姆(Guido van Rossum),别称:龟叔(Guido). (2) python具有非常多并且强大的第三方库,使得程序开发起来 ...
随机推荐
- 圆角标题title
Html代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- IE8引入JavaScript
错误写法 : <script type="application/javascript"> 正确写法 <script type="text/ja ...
- tcp 建立连接的三次握手,以及关闭连接的4次挥手
TCP连接的三次握手 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; (客户端问服务器:你爱我吗?) 第二次握手:服务器收到syn包,必须确认客户的 ...
- 01. css sprite是什么,有什么优缺点?
1.css sprite是什么,有什么优缺点? 通常被意译为“CSS图像拼合”或“CSS贴图定位” 1)CSS Sprites的优点 利用CSS Sprites能很好地减少网页的http请求,从而大大 ...
- POJ_3268 Silver Cow Party 【最短路】
一.题面 POJ3268 二.分析 该题的意思就是给定了一个由每个节点代表农场的有向图,选定一个农场X办party,其余农场的都要去,每个农场的cow都走最短路,走的时间最久的cow耗时多少. 了解题 ...
- C#集合之不变的集合
如果对象可以改变其状态,就很难在多个同时运行的任务中使用.这些集合必须同步.如果对象不能改变器状态,就很容易在多个线程中使用. Microsoft提供了一个新的集合库:Microsoft Immuta ...
- autokeras 在windows10下的安装与使用
注意:autokeras只适用于python3.6 先打开命令行(cmd), 输入 python --version 查看python版本,是否需要降级和升级. 降级的命令如下: conda inst ...
- 论文阅读 | CenterNet:Object Detection with Keypoint Triplets
相关链接 论文地址:https://arxiv.org/abs/1904.08189 代码链接:https://github.com/Duankaiwen/CenterNet 概述 CenterNet ...
- 4.nginx高可用
1.大体结构 一.使用场景介绍: nginx做负载均衡,来达到分发请求的目的,但是不能很好的避免单点故障,假如nginx服务器挂点了,那么所有的服务也会跟着瘫痪 .keepalived+nginx,就 ...
- 转:五年java人的一点感悟
转自:五年java人的一点感悟 恍然间,发现自己在这个行业里已经摸爬滚打了五年了,原以为自 己就凭已有的项目经验和工作经历怎么着也应该算得上是一个业内比较资历的人士了,但是今年在换工作的过程中却遭到了 ...