[提问] Golang Go语言中,刚接触,想问一下为什么不能序列化 html 包里面的 Node 类型?

发布于 1周前 作者 yuanlaile 来自 Go语言

[提问] Golang Go语言中,刚接触,想问一下为什么不能序列化 html 包里面的 Node 类型?

代码如下:

node, _ := html.Parse(response.Body)
nodeString,err := json.Marshal(node)
fmt.Println(err)

报异常如下:
json: unsupported value: encountered a cycle via *html.Node

是因为 Node 包含了*Node 类型的字段?对于这种循环嵌套的对象有办法做到序列化吗?
附 Node 的代码

type Node struct {
	Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
Type      NodeType
DataAtom  atom.Atom
Data      string
Namespace string
Attr      []Attribute

}


更多关于[提问] Golang Go语言中,刚接触,想问一下为什么不能序列化 html 包里面的 Node 类型?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

10 回复

一般来讲,受限于 go 的强权限控制和弱鸡反射,正常的 go 用户不会选择直接序列化一个内部使用的结构体,你可以选择定义一个用于数据交换的结构体进行序列化和反序列化

更多关于[提问] Golang Go语言中,刚接触,想问一下为什么不能序列化 html 包里面的 Node 类型?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我主要是想打印出来看看这个实体的结构和内容 goland debug 下显示的结构看的我很难受。。。 另外问一下 goland 的调试是不可逆的吗?别的语言都支持拖拽调试的游标,goland 怎么才能回到前几步?

https://pkg.go.dev/golang.org/x/net/html?tab=doc#Node 看定义,字段全都是公有的,何来“内部使用的结构体”?

报错都告诉你原因了,有环,也就是有 *html.Node 类型的成员指向了自身。这种带环的结构,换成任何语言,都很难序列化。

试试 litter

退回前几步?应该都是可以的,不就是倒回去之前几个栈嘛,如果你觉得还不够,要不上 mozilla 的 rr debugger

其实,C#一直都有对带环对象的序列化支持。

#3 啊是我瞎了,昨晚有点困没看清

没找到。。 比如 idea 和 rider,debug 的时候游标是可以随便拖的,goland 根本不能拖

感谢 非常有用 就是我想找到功能!

在Go语言中,html 包里的 Node 类型不能直接被序列化(比如通过 encoding/jsonencoding/xml 等包)的原因主要是其复杂性和循环引用问题。

Node 类型是一个接口,它表示 HTML 文档树中的一个节点。这个接口可以表示元素节点、文本节点、文档节点等多种类型,而这些类型在内部可能包含对其他 Node 的引用。这种结构导致几个序列化上的问题:

  1. 接口序列化:Go的序列化库通常不支持直接序列化接口,因为接口是动态的,没有固定的结构。

  2. 循环引用:HTML文档树中经常存在父子节点间的循环引用(例如,一个节点是其子节点的父节点),而大多数序列化格式不支持循环引用,这会导致序列化失败或产生无限递归。

  3. 类型信息丢失:即使可以序列化,如何保留和恢复 Node 的具体类型信息也是一个挑战。

要解决这个问题,通常的做法是定义一个自定义的结构体来表示你需要序列化的数据,这个结构体应该避免上述问题。例如,你可以创建一个只包含你需要序列化的字段(如节点类型、标签名、文本内容等)的结构体,并手动遍历 Node 树来填充这些字段。这样,你就可以控制哪些数据被序列化,以及如何表示这些数据。

回到顶部