版本:
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的角度来看):
顺便比较一下 iface 和 eface 的区别:


可看到 调用方(编译器)就根据自己想的创建了这么一个 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
}
values := make(url.Values)这个是一个map[string] []stringval := reflect.ValueOf(v)reflect.ValueOf(v) 传入一个interface{}返回一个Value.
看看他到底做了什么?

他实际上 就是吧interface 稍微加工了一下,里面的 人rtype 和 unsafe.Pointer 和 interface 中的指针指向的是差不多的东西。
可以相当于是wrapper了interface一下让这个value更好用,能用很多 reflect包中的函数。
- 后面的基本上都是一些检查的工作了,跟真正的解析没有关系。
总结:
Values 上层代码的逻辑就是
func Values(v interface{}) (url.Values, error) {
// 1. 对外提供好看的接口 interface{}
// 2. 上层函数提供 buffer, 这么做的理由
// 上层函数尽量不隐藏cost(一些内存分配在这个函数中产生, 而不要让下层函数去创建buffer),
// 只让下层函数做一些逻辑任务,不涉及内存分配
// 3. 做一些错误校验的工作
// 4. 根据校验结果调用下层函数
}
本文通过分析go-querystring库的源码,深入探讨Go中的反射机制和interface的使用。文章首先介绍了如何利用反射解析struct,接着分析了调用方与被调用方的行为差异,尤其是`reflect.ValueOf()`函数在其中的作用,它将interface包装以提供更丰富的操作。最后,文章总结了上层代码逻辑与接口解析的关键点。
2350

被折叠的 条评论
为什么被折叠?



