如何使用作为接口参数传递的结构体来操作解码后的 XML?

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

How to manipulate decoded XML with Struct passed in as interface parameter

问题

有没有办法使用作为接口参数传递的结构体来操作解码后的 XML?

我将结构体作为参数传递,但在使用 xml.Decode 解码后,我无法指定其字段以将其字段作为结构体检索出来。我认为 Go 在没有明确指定时会抱怨它不知道要查找哪个结构体。

下面是一个示例函数:

func UpdateEntity(response *restful.Response, xml_template string, dataStruct interface{}, respStruct interface{}) (*restful.Response, interface{}) {
    payload := renderCachedTemplate(response, xml_template, dataStruct)
    resp, err := http.Post(url, "application/xml", payload)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return nil, nil
    }

    defer resp.Body.Close()
    dec := xml.NewDecoder(resp.Body)

    if err = dec.Decode(respStruct); err != nil {
        fmt.Printf("error: %v", err)
        return nil, nil
    }
    return response, respStruct
}

func main() {
   resp, respStruct := UpdateEntity(response, "template.xml", LoginStruct{}, UserStruct{})
   fmt.Println(respStruct.Username)
}

这一行 fmt.Println(respStruct.Username) 抱怨 Username 未定义,因为 interface{} 没有 Username 字段或方法。

我将 UserStruct 作为 respStruct 参数传递,例如,它具有 Username 字段。

有没有办法使用 interface{} 返回变量并使用预定义的结构体字段?

英文:

Is there a way to manipulate decoded XML with struct passed in as interface parameter?

I'm passing struct as a parameter which has interface type but after decoding it with xml.Decode I cannot specify its fields to retrieve its fields as structs. I think go is complaining that it doesn't know which struct to look for unless it's specifically mentioned.

Below is an example function:

func UpdateEntity(response *restful.Response, xml_template string, dataStruct interface{}, respStruct interface{}) (*restful.Response, interface{}) {
	payload := renderCachedTemplate(response, xml_template, dataStruct)
	resp, err := http.Post(url, "application/xml", payload)
	if err != nil {
		response.WriteErrorString(http.StatusInternalServerError, err.Error())
		return nil, nil
	}

	defer resp.Body.Close()
	dec := xml.NewDecoder(resp.Body)

	if err = dec.Decode(respStruct); err != nil {
		fmt.Printf("error: %v", err)
		return nil, nil
	}
	return response, respStruct
}

func main() {
   resp, respStruct := UpdateEntity(response, "template.xml", LoginStruct{}, UserStruct{})
   fmt.Println(respStruct.Username)
}

This line fmt.Println(respStruct.Username) complains Username is not defined as interface{} has no field or method Username.

I'm passing UserStruct as its respStruct parameter which has Username field for example.

Is there a way I can use interface{} return variable and use pre-defined Struct fields?

答案1

得分: 2

将函数更改为接受一个指向值的指针,而不是返回该值:

func UpdateEntity(response *restful.Response, xml_template string, dataStruct interface{}, respStruct interface{}) *restful.Response {
    payload := renderCachedTemplate(response, xml_template, dataStruct)
    resp, err := http.Post(url, "application/xml", payload)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return nil
    }

    defer resp.Body.Close()
    dec := xml.NewDecoder(resp.Body)

    if err = dec.Decode(respStruct); err != nil {
        fmt.Printf("error: %v", err)
        return nil
    }
    return response
}

将指向值的指针传递给函数,并在函数调用后使用更新后的值:

func main() {
   var respStruct UserStruct
   resp := UpdateEntity(response, "template.xml", LoginStruct{}, &respStruct)
   fmt.Println(respStruct.Username)
}

因为Decode方法需要一个指向值的指针,所以这个更改也修复了原始代码中的错误。

英文:

Change the function to expect a pointer to a value instead of returning the value:

func UpdateEntity(response *restful.Response, xml_template string, dataStruct interface{}, respStruct interface{}) *restful.Response {
	payload := renderCachedTemplate(response, xml_template, dataStruct)
	resp, err := http.Post(url, "application/xml", payload)
	if err != nil {
		response.WriteErrorString(http.StatusInternalServerError, err.Error())
		return nil
	}

	defer resp.Body.Close()
	dec := xml.NewDecoder(resp.Body)

	if err = dec.Decode(respStruct); err != nil {
		fmt.Printf("error: %v", err)
		return nil
	}
	return response
}

Pass a pointer to your value to the function and then use the updated value after the function call:

func main() {
   var respStruct UserStruct
   resp := UpdateEntity(response, "template.xml", LoginStruct{}, &respStruct)
   fmt.Println(respStruct.Username)
}

Because the Decode method expects a pointer to a value, this change also fixes an error in the original code.

huangapple
  • 本文由 发表于 2014年10月20日 20:52:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/26466184.html
匿名

发表评论

匿名网友

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

确定