【问题标题】:Structures with Interface Members and Pointer Receivers具有接口成员和指针接收器的结构
【发布时间】:2020-01-13 03:15:30
【问题描述】:

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

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

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")
}

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

这是下面代码的工作副本:

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
}

【问题讨论】:

    标签: go


    【解决方案1】:

    鉴于此结构:

    type node struct {
        data  int
        left  btree
        right btree
    }
    

    以及带有q指针接收器的函数f

    func (n *node) f() {}
    

    f 获得指向node 的指针。 f 对节点 n 所做的任何更改都将反映在用于调用 f 的副本上。

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

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

    希望这会有所帮助。

    【讨论】:

    • “您的回复”的前两段是有道理的,但我在最后一段(最后一段)上迷路了。您是在谈论(例如)节点的add方法中的左右分支吗?
    • 我认为我需要对接口和值/指针接收器进行一些补救工作。快的!去谷歌洞穴。
    猜你喜欢
    • 2018-01-20
    • 2019-11-23
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 2012-03-12
    • 2010-11-22
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多