在链表的节点实现中,golang结构体和java类的区别

1、java中的类

在java中实现一个链表,链表中的节点类我们一般用下面的Node类这种构造方式

class Node {
    int value;
    Node next;
}

其中,value属性保存该节点的值,next属性保存该节点的下一个节点的指针

2、golang的结构体

在golang中,类比java中类的实现,我们一般很容易写出这样的结构体实现

type Node struct {
    value int
    next Node
}

其中value保存该节点的值,next属性保存该节点的下一个节点的地址。但是这段代码会在编译器中报告 invalid recursive type Node 这个错误。这是因为golang的编译器会认为Node这个结构体里面还引用了一个Node结构体,这样一直递归下去,编译器不知道给Node这个结构体分配多少空间。

所以golang中节点的结构体应该是

type Node struct {
    value int
    next *Node
}

其中next是一个Node的指针类型,由于指针的空间大小是确定的(在32位机器上占用4个字节,在64位机器上占用8个字节),这样编译器就知道给Node这个结构体分配多少空间了,不会产生递归的问题。

3、思考

1、为什么java中可以在类的属性中引用自己本身呢?

因为在java中我们这样定义一个类

class Node {
    int value;
    Node next;
}

但是在java的解释器中,代码会这样解释

class Node {
    int value;
    *Node next;
}

解释器会自动将其解释成指针类型,这样就不会产生golang中递归调用的问题

2、golang中结构体不能引用自身,能引用别的结构体吗?
type A struct {    
}
type B struct {
    a A
}

如图,在B结构体中引用A结构体,这样代码不会报错,因为A的结构体的大小编译器已知。但是如果改成

type A struct {
    b B
}
type B struct {
    a A
}

这样代码又会报 invalid recursive type Node 这个错误,因为编译器不知道A和B的确切大小。所以以后在代码中为了防止出现这种错误,在结构体中引用其他的结构体一般最好都设置为指针类型。

4、参考

https://www.jianshu.com/p/f3b88513dbd8

https://www.codenong.com/8261058/

https://stackoverflow.com/questions/59935466/invalid-recursive-type-and-illegal-cycle-in-declaration-of

你可能感兴趣的:(golang)