go - 具有接口(interface)成员和指针接收器的结构

标签 go

我正在创建一个简单的排序二叉树,它是不可变的(它应该表现得像它的不可变),我不确定指针接收器在传递带有接口(interface)的结构时如何工作。

这是我定义二叉树的方式。

type btree interface {
    display(io.Writer)
    add(int) btree
    replace(int, int)//A test to see if we are sharing nodes
}

二叉树节点定义如下:
type node struct {
    data  int
    left  btree
    right btree
}

和空的二叉树节点
type empty struct{}

功能与方法
func createEmpty() btree {
    return &empty{}
}

节点结构的方法
//replace is just a test to see if I'm sharing nodes
func (n *node) replace(value, replacement int) {
    if n.data < value {
        n.left.replace(value, replacement)
    } else if n.data > value {
        n.right.replace(value, replacement)
    } else {
        n.data = replacement
    }
}

func (n *node) add(data int) btree {
    if n.data < data {
        l := &node{n.data, n.left.add(data), n.right}
        return l
    } else if n.data > data {
        r := &node{n.data, n.left, n.right.add(data)}
        return r
    } else {
        return n
    }
}

func (n *node) display(w io.Writer) {
    n.left.display(w)
    fmt.Fprintln(w, n.data)
    n.right.display(w)
}

空节点的方法
//replace is just a test to see if I'm sharing nodes
func (*empty) replace(_, _ int) {}

func (e *empty) add(data int) btree {
    en := &node{data, e, e}
    return en
}

func (*empty) display(w io.Writer) {
    fmt.Fprintln(w, "Empty")
}

请注意,代码确实按预期工作,但我不确定当我将带有接口(interface)成员的结构传递给指针接收器时会发生什么。接口(interface)数据结构是否被复制,但只是一个浅拷贝,所以它指向的数据保持不变?在这种情况下,是否有关于接口(interface)会发生什么的文档?

这是以下代码的工作副本:
package main

import (
    "fmt"
    "io"
    "os"
)

func createEmpty() btree {
    return &empty{}
}

type btree interface {
    display(io.Writer)
    add(int) btree
    replace(int, int)
}

type node struct {
    data  int
    left  btree
    right btree
}

func (n *node) replace(value, replacement int) {
    if n.data < value {
        n.left.replace(value, replacement)
    } else if n.data > value {
        n.right.replace(value, replacement)
    } else {
        n.data = replacement
    }
}

func (n *node) add(data int) btree {
    if n.data < data {
        l := &node{n.data, n.left.add(data), n.right}
        return l
    } else if n.data > data {
        r := &node{n.data, n.left, n.right.add(data)}
        return r
    } else {
        return n
    }
}

func (n *node) display(w io.Writer) {
    n.left.display(w)
    fmt.Fprintln(w, n.data)
    n.right.display(w)
}

type empty struct{}

func (*empty) replace(_, _ int) {}

func (e *empty) add(data int) btree {
    en := &node{data, e, e}
    return en
}

func (*empty) display(w io.Writer) {
    fmt.Fprintln(w, "Empty")
}

func main() {
    bt := createEmpty().add(5).add(1).add(8).add(2)
    bt2 := bt.add(7).add(6).add(10).add(9)
    bt.display(os.Stdout)
    fmt.Fprintln(os.Stdout, "\n--->")
    bt2.display(os.Stdout)
    fmt.Fprintln(os.Stdout, "\n\n--->")
    //The node with 1 should be shared with bt and bt2
    //so if we change bt's node 1 to 4143
    //we should see the change in bt2 too   
    bt.replace(1, 4143)
    bt.display(os.Stdout)//We see the change here, 1 is now 4143
    fmt.Fprintln(os.Stdout, "\n--->")
    bt2.display(os.Stdout)//We see the change here, 1 is now 4143
}

最佳答案

鉴于这种结构:

type node struct {
    data  int
    left  btree
    right btree
}

和函数 f使用 q 指针接收器:
func (n *node) f() {}
f获得指向 node 的指针.任何更改f使节点 n将反射(reflect)在用于调用 f 的副本上.

更准确地说,当您调用 n.f()如果 n*node ,然后将该指针的副本发送到 f ,它仍然指向与 n 相同的对象.如果 n不是指针,则&n将发送至f .

为了让您的代码正常工作,左右 btree接口(interface)还应该包含 *node s,而不是 node s(你已经正确地做到了)。这是因为,例如,如果您调用 node.left.replace ,您想要 node.left 中的值将被替代。如果您有 replace 的值接收器函数,那么当你调用 node.left.replace该左节点的副本将被发送到 replace用作接收器,修改在 node.left 上不可见节点。

希望这可以帮助。

关于go - 具有接口(interface)成员和指针接收器的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59706822/

相关文章:

function - 在结构上调用函数的正确习惯用法是什么?

firebase - 无法在返回值中使用类型的变量

node.js - 用一种语言或库创建的 jwt 可以用另一种语言或库进行解码和验证吗?

json - Go json.Unmarshal() 适用于单个实体但不适用于 slice

声明为变量的函数的 Golang 测试(作证)

go - GO中小写字母开头怎么暴露错误接口(interface)?

node.js - 通过 Node 调用golang函数时无法打开文件

database - 在PostgreSQL中联接两个表,其中一个内容为Array字段,另一个为该数组的主表

go - 在go-plus atom中按项目添加gopath

go - 无法使用validator.v2 golang进行验证