面试题答案
一键面试设计思路
- 定义新的结构体:定义一个新的结构体,该结构体嵌入
xml.Name
来保留XML标签的基本信息,同时添加一个字段来存储解密后的值。 - 实现
xml.Unmarshaler
接口:为新定义的结构体实现xml.Unmarshaler
接口。在UnmarshalXML
方法中,先按照常规方式解析XML标签的值,然后对该值进行解密操作。 - 结合标准
xml
包:在需要解析特殊XML的地方,使用自定义的结构体替代原来的结构体,并利用标准xml.Unmarshal
函数进行解析。
关键代码实现
package main
import (
"encoding/xml"
"fmt"
)
// 假设的加密算法函数
func decrypt(data string) string {
// 这里只是示例,实际应实现具体的解密逻辑
return data + "_decrypted"
}
// 自定义结构体,实现xml.Unmarshaler接口
type EncryptedXMLValue struct {
xml.Name
Value string `xml:",chardata"`
}
func (e *EncryptedXMLValue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var v struct {
Value string `xml:",chardata"`
}
if err := d.DecodeElement(&v, &start); err != nil {
return err
}
e.Name = start.Name
e.Value = decrypt(v.Value)
return nil
}
// 示例XML结构
type ExampleXML struct {
XMLName xml.Name `xml:"example"`
Values []EncryptedXMLValue `xml:"value"`
}
与标准xml包解析功能结合
func main() {
xmlData := []byte(`
<example>
<value>encrypted_value_1</value>
<value>encrypted_value_2</value>
</example>
`)
var ex ExampleXML
if err := xml.Unmarshal(xmlData, &ex); err != nil {
fmt.Printf("解析错误: %v\n", err)
return
}
for _, v := range ex.Values {
fmt.Printf("标签: %s, 解密后的值: %s\n", v.Name.Local, v.Value)
}
}
在上述代码中:
decrypt
函数是假设的解密函数,实际应用中应替换为真实的解密逻辑。EncryptedXMLValue
结构体实现了xml.Unmarshaler
接口,在UnmarshalXML
方法中先解析XML值,再进行解密。ExampleXML
结构体包含EncryptedXMLValue
类型的切片,用于存储解析后的解密值。- 在
main
函数中,通过标准的xml.Unmarshal
函数将XML数据解析到ExampleXML
结构体中,实现了自定义解码器与标准xml
包解析功能的结合。