• grpc服务端转换protobuf到http请求参数query


    前提

    grpc服务接收到request的请求后,需要把参数转换成http,去请求其他接口。

    使用go作为grpc的服务端,数据协议是protobuf

    想到的几种解决方案:

    • 1.编译好的pb.go文件里有个string(),可以把所有参数都打印出来,参数之间是空格隔开的,参数和值是k:v的形式,但是不带引号,不是json格式

    • 2.把接收到的数据转换为json,直接以json的格式,发送请求

    • 3.根据传过来的request反射到固定的struct上,得到具体的属性和获取此属性的方法,再加入到url.values{},再encode()发送请求

    实现

    方案1

    方案1是比较简单的,用空格分割,得到参数和值,再根据":"分割得到参数、值,再加入到url.values{}

    代码如下:

    param := url.Values{}
    //得到请求的字符串形式
    rs := strings.Split(request.String(), " ")
    	for _, v := range rs {
    		if v != "" {
    			vv := strings.Split(v, ":")
    			param.Add(vv[0], strings.Trim(vv[1], """))
    			vv := strings.SplitN(v, ":", 2)
    			//转换成
    			val, e := strconv.Unquote(vv[1])
    			log.Print(val, e)
    			if e == nil {
    				param.Add(vv[0], val)
    			}
    		}
    	}
    
    
    

    前期运行OK,后期遇到了两个问题:

    • 1.提交的值里有空格时,分割会有问题
    • 2.得到的中文是utf8字符

    放弃方案1

    方案2

    把数据先转成json,再解析成map[string]string 的形式,目的是为了省去值都转换为string

    str, _ := json.Marshal(request)
    	jsonstr := string(str)
    
    	m := make(map[string]interface{})
    	e := json.Unmarshal([]byte(jsonstr), &m)
    	param := url.Values{}
    	if e != nil {
    		return param
    	}
    
    	for k, v := range m {
    		sv := fmt.Sprint(v)
    		param.Add(k, sv)
    	}
    

    结果:对于中文还有空格的问题是解决了,不过会把int64的数字类型转换成float类型,转换有问题

    方案3

    根据go的reflect包反射出实际的struct,go编译pb的文件里struct里属性名和proto文件不一样,需要根据属性的tag得到实际的参数名

    代码如下:

    	ty := reflect.TypeOf(request).Elem()
    	#得到struct的属性数量
    	fieldnum := ty.NumField()
    	
    	#实际数据的指针
    	ob := reflect.ValueOf(request)
    	param := url.Values{}
    	#由于编译好的属性最后3位不用
    	for i := 0; i < fieldnum-3; i++ {
    		f := ty.Field(i).Tag.Get("json")
    		fv := strings.Split(f, ",")
    		k := fv[0]
    
    		fieldname := ty.Field(i).Name
    		ret := ob.MethodByName("Get" + fieldname).Call(nil)
    		if !ret[0].IsZero() {
    			# 这一步,用了很巧的办法把各个类型转换成了string才能加入到param里
    			v := fmt.Sprint(ret[0])
    			param.Add(k, v)
    		}
    	}
    	return param
    
  • 相关阅读:
    Android studio ButterKnife插件
    Android Studio Prettify 插件
    Android studio的主题颜色修改
    MeasureSpec 的三中类型
    android 加载远程Jar、APK
    android源码 键盘消息处理机制
    Android源码阅读笔记二 消息处理机制
    phpstrom 激活
    sublime vue 语法高亮插件安装
    mysql登录报错“Access denied for user 'root'@'localhost' (using password: YES”的处理方法
  • 原文地址:https://www.cnblogs.com/efan/p/12061823.html
Copyright © 2020-2023  润新知