在不知道类型并依赖于接口的函数中解组(Unmarshal)Golang结构体

huangapple go评论85阅读模式
英文:

golang Unmarshall Struct In Function that do not know the type and rely on interface

问题

这是我需要做的事情,但找不到所需的资源来完成它:

我需要编写一个通用函数,用于设置MOCK服务器的处理程序。该处理程序将接收一个JSON对象,并且必须对其进行解组并将其与参考结构进行比较,并根据两个对象之间的对应关系设置其状态。
这是关键:在函数内部,我们不知道参考的类型是什么。

<===== 我在这一点上是什么情况 ====>
我编写了这个不起作用的函数。

func createHandlerToTestDelete(route string, ref interface{}, received interface{}){
	Servmux.HandleFunc(route,
		func(w http.ResponseWriter, r *http.Request) {
			// 从请求体中重新创建一个结构体
			body, _ := ioutil.ReadAll(r.Body)
			json.Unmarshal(body, &amp;received)
			
			// ref 和 received 进行比较
			if reflect.DeepEqual(received, ref) {
				w.WriteHeader(http.StatusOK)
			} else {
				w.WriteHeader(http.StatusInternalServerError)
			}
		},
	)
}

这是我如何使用它的方式:

ref := MyStruct{...NotEmpty...}
received := MyStruct{}
createHandlerToTestDelete("aRoute", ref, received)

结果是,当服务器执行解组操作时,不会关心接收变量的原始类型。

有人有什么想法吗?

英文:

here is what I need to do and can't find the resource I need in order to do it:

I need to write a generic function that will setup a handler for a MOCK server. This handler will receive a JSON object and have to unMarshall it and compare it to a reference structure and set its status accordingly depending on the correspondence between both object.
Here is the trick: we do not know inside the function what is the type of the reference.

<===== Where am I at this point ====>
I wrote this function, which doesn't work.

func createHandlerToTestDelete(route string, ref interface{}, received interface{}){
	Servmux.HandleFunc(route,
		func(w http.ResponseWriter, r *http.Request) {
			// recreate a structure from body content
			body, _ := ioutil.ReadAll(r.Body)
			json.Unmarshal(body, &amp;received)
			
			// comparison between ref and received
			if reflect.DeepEqual(received, ref) {
				w.WriteHeader(http.StatusOK)
			} else {
				w.WriteHeader(http.StatusInternalServerError)
			}
		},
	)
}

here is how I am using it:

ref := MyStruct{...NotEmpty...}
received := MyStruct{}
createHandlerToTestDelete(&quot;aRoute&quot;, ref, received)

The result is that the server when doing Unmarshal will not care of the original type of the received variable.

Does someone has an idea?

答案1

得分: 1

使用reflect.New来创建一个与引用类型相同的值的指针。

func createHandlerToTestDelete(route string, ref interface{}) {
  t := reflect.TypeOf(ref)
  ServeMux.HandleFunc(route,
    func(w http.ResponseWriter, r *http.Request) {
      v := reflect.New(t)
      if err := json.NewDecoder(r.Body).Decode(v.Interface()); err != nil {
        // 处理错误
      }
      // v 是值的指针。获取元素以进行正确的比较。
      if reflect.DeepEqual(v.Elem().Interface(), ref) {
        w.WriteHeader(http.StatusOK)
      } else {
        w.WriteHeader(http.StatusInternalServerError)
      }
    },
  )
}
英文:

Use reflect.New to create a pointer to a value with the same type as the reference type.

func createHandlerToTestDelete(route string, ref interface{}) {
  t := reflect.TypeOf(ref)
  ServeMux.HandleFunc(route,
	func(w http.ResponseWriter, r *http.Request) {
		v := reflect.New(t)
		if err := json.NewDecoder(r.Body).Decode(v.Interface()); err != nil {
			// handle error
		}
        // v is pointer to value. Get element for correct comparison.
		if reflect.DeepEqual(v.Elem().Interface(), ref) {
			w.WriteHeader(http.StatusOK)
		} else {
			w.WriteHeader(http.StatusInternalServerError)
		}
	},
  )
}

huangapple
  • 本文由 发表于 2017年3月9日 00:56:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/42677310.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定