Go中的反射、interface的使用和原理,基于go-querystring/query的源码分析

本文通过分析go-querystring库的源码,深入探讨Go中的反射机制和interface的使用。文章首先介绍了如何利用反射解析struct,接着分析了调用方与被调用方的行为差异,尤其是`reflect.ValueOf()`函数在其中的作用,它将interface包装以提供更丰富的操作。最后,文章总结了上层代码逻辑与接口解析的关键点。

版本:

github.com/google/go-querystring v1.1.0

使用方法:

query.Values(opt) 用来解析一个 struct 结构题:

调用方:

func main () {
	type Options struct {
		Query   string `url:"q"`
		ShowAll bool   `url:"all"`
		Page    int    `url:"page"`
	}

	opt := Options{ "foo", true, 2 }
	v, _ := query.Values(opt)
	fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
}

调用方行为(从caller的角度来看):

顺便比较一下 ifaceeface 的区别:

在这里插入图片描述

在这里插入图片描述

可看到 调用方(编译器)就根据自己想的创建了这么一个 interface 给 这个函数。

callee 做的事情:

func Values(v interface{}) (url.Values, error) {
	values := make(url.Values)
	val := reflect.ValueOf(v)
	for val.Kind() == reflect.Ptr {
		if val.IsNil() {
			return values, nil
		}
		val = val.Elem()
	}

	if v == nil {
		return values, nil
	}

	if val.Kind() != reflect.Struct {
		return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind())
	}

	err := reflectValue(values, val, "")
	return values, err
}
  1. values := make(url.Values) 这个是一个map[string] []string
  2. val := reflect.ValueOf(v) reflect.ValueOf(v) 传入一个interface{}返回一个 Value.

看看他到底做了什么?

在这里插入图片描述

他实际上 就是吧interface 稍微加工了一下,里面的 人rtype 和 unsafe.Pointer 和 interface 中的指针指向的是差不多的东西。

可以相当于是wrapper了interface一下让这个value更好用,能用很多 reflect包中的函数。

  1. 后面的基本上都是一些检查的工作了,跟真正的解析没有关系。

总结:

Values 上层代码的逻辑就是

func Values(v interface{}) (url.Values, error) {
	// 1. 对外提供好看的接口 interface{}
	// 2. 上层函数提供 buffer, 这么做的理由
	//       上层函数尽量不隐藏cost(一些内存分配在这个函数中产生, 而不要让下层函数去创建buffer), 
  //       只让下层函数做一些逻辑任务,不涉及内存分配
	// 3. 做一些错误校验的工作
	// 4. 根据校验结果调用下层函数
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值