gout 使用笔记3
目前使用gout 作为http客户端, 处理数据时看到了respone数据解析。
首先看解析respone header数据:
目前看代码的核心设计逻辑:
1、创建一个Header = headerDecode{} 实例
2、调用实例的(h *headerDecode) Decode(rsp *http.Response, obj interface{}) error 方法
3、如果是传入的obj(BindJSON(&rsp) rsp就是obj) 是http.Header类型也就是type Header map[string][]string类型,
则直接遍历rsp 响应头数据返回即可
case http.Header: for k, v := range rsp.Header { value[k] = v } return nil
如果是*http.Header 也就是*map[string][]string 类型,直接将resp heard copy一份即可
case *http.Header: *value = rsp.Header.Clone() return nil
4、否则安装struct 类型来解析decode(headerSet(rsp.Header), obj, "header")---->
decodeCore(val reflect.Value, sf reflect.StructField, setter setter, tagName string) (err error)
type headerSet map[string][]string var _ setter = headerSet(nil) func (h headerSet) Set(value reflect.Value, sf reflect.StructField, tagValue string) error { return setForm(h, value, sf, textproto.CanonicalMIMEHeaderKey(tagValue)) }
其中val := reflect.ValueOf(obj) 对传入的obj 获取反射值
func decodeCore(val reflect.Value, sf reflect.StructField, setter setter, tagName string) (err error) { vKind := val.Kind() // elem pointer for vKind == reflect.Ptr { val = val.Elem() vKind = val.Kind() } // 每个类型都会先尝试set // 如果不是结构体才设置。那time.Time类型该如何呢? // (time.Time是标准库里面用于表示时间的类型, 用结构体实现)? if vKind != reflect.Struct || !sf.Anonymous { //todo 是否已经设置过 err := parseTagAndSet(val, sf, setter, tagName) if err != nil { return err } } //对于一开始val为struct, 获取val,struct type, 然后解析struct 每个filed, 以及对应的val.Field(i) if vKind == reflect.Struct { typ := val.Type() for i := 0; i < typ.NumField(); i++ { sf := typ.Field(i) if sf.PkgPath != "" && !sf.Anonymous { continue } if err = decodeCore(val.Field(i), sf, setter, tagName); err != nil { return } } } return nil }
处理struct 每个Field 的tagname value
func parseTagAndSet(val reflect.Value, sf reflect.StructField, setter setter, tagName string) error { tagName = sf.Tag.Get(tagName) tagName, _ = parseTag(tagName) if tagName == "" { tagName = sf.Name---->复制tagname } if tagName == "" { return nil } return setter.Set(val, sf, tagName) //---> setter 指向的也就是headerSet(rsp.Header)--->rsp.Header
}
根据 一开始创建来的 rsp.header , struct.Field(i)的tagname 以及reflect value
根据rsp.header 读取 tagname 对应的val, 然后设置reflect value 为 val
func setForm(m map[string][]string, value reflect.Value, sf reflect.StructField, tagValue string, ) error { vs, ok := m[tagValue] if !ok { //fmt.Printf("tagName = %s:%v\n", tagValue, m) return nil } switch value.Kind() { case reflect.Slice: return setSlice(vs, sf, value) case reflect.Array: if len(vs) != value.Len() { return fmt.Errorf("%q is not valid value for %s", vs, value.Type().String()) } return setArray(vs, sf, value) } var val string if len(vs) > 0 { val = vs[0] } return setBase(val, sf, value) }
package main import "fmt" func main() { var i interface{} = 42 // Type assertion to extract the underlying concrete value as an int. if val, ok := i.(int); ok { fmt.Printf("i is an int: %d\n", val) } else { fmt.Println("i is not an int") } switch val := i.(type) { case int: fmt.Printf("i is an int: %d\n", val) case string: fmt.Printf("i is a string: %s\n", val) default: fmt.Println("i is of an unknown type") } }
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2021-08-01 redis:字典-hash