Golang – 通过接口获取结构体字段的指针

huangapple go评论69阅读模式
英文:

Golang - Get a pointer to a field of a struct through an interface

问题

我正在非常早期的了解Go语言中的接口。我正在编写一些逻辑模拟,并有以下类似的代码(这里我进行了大量简化):

请参考我的问题的注释:

type LogicNode struct {
    Input    *bool
    Output   *bool
    Operator string
    Next     Node
}

func (n *LogicNode) Run() {
    // 在这里做一些事情
    n.Next.Run()
}

type Node interface {
    Run()
}

func main() {

    nodes := make([]Node, 1000)

    for i := 0; i < 1000; i++ {
        n := LogicNode{
            // 分配值等等。
        }
        nodes[i] = &n
    }

    for i, node := range nodes {
        // 我需要在这里访问LogicNode的Output指针,作为*bool类型。
        // 这样我就可以将相同的地址设置给其他Node的Input,从而"连接"它们。
        // 但是我只能得到类似这样的东西:

        x := reflect.ValueOf(node).Elem().FieldByName("Output")

        // 它是<*bool Value>
        // 我找不到一种方法来将一个新的*bool设置到底层(LogicNode)结构的Input或Output中...
    }
}

我使用接口的原因是因为还有其他节点类型,如FloatNode和MathNode等,它们具有不同的字段,但它们实现了自己的run方法。

我成功地使用了Value的SetString或SetBool方法,但无法在那里设置指针... 提前感谢您的帮助。

英文:

I'm at a very early stage of understanding interfaces in Go. I'm writing some logical simulations and have something like the following code (I heavily simplify here):

Please see the comments for my question:

type LogicNode struct {
	Input   *bool
	Output   *bool
	Operator string
	Next     Node
}

func (n *LogicNode) Run() {
	// do some stuff here
	n.Next.Run()
}

type Node interface {
	Run()
}

func main() {

	nodes := make([]Node, 1000)

	for i := 0; i &lt; 1000; i++ {
		n := LogicNode{
            //assign values etc.
		}
		nodes[i] = &amp;n
	}

    for i, node := range nodes {
	    // I need to access LogicNode&#39;s Output pointer here, as a *bool.
        // so I can set the same address to other Node&#39;s Input thereby &quot;connecting&quot; them.
        // but I could only get something like this:

        x := reflect.ValueOf(node).Elem().FieldByName(&quot;Output&quot;)

        // which is &lt;*bool Value&gt;
        // I couldn&#39;t find a way to set a new *bool to the underlying (LogicNode) Struct&#39;s Input or Output..
	}
}

The reason I'm using interfaces is because there are other node types FloatNode MathNode etc. which have different fields, but they implement their own run method.

I've successfully used Value's SetString or SetBool methods, but can't set a pointer there... Thanks in advance.

答案1

得分: 10

你可以使用Set泛型版本来更新字段的值:

package main

import (
	"fmt"
	"reflect"
)

type LogicNode struct {
    Input    *bool
    Output   *bool
    Operator string
    Next     Node
}

func (n *LogicNode) Run() {
    // 在这里做一些操作
    // n.Next.Run()
    fmt.Printf("LogicNode.Input = %v (%v)\n", *n.Input, n.Input)
}

type Node interface {
    Run()
}

func main() {
    input := false
    input2 := true
    fmt.Printf("Input1 = %v (%v)\n", input, &input)
    fmt.Printf("Input2 = %v (%v)\n", input2, &input2)
    var node Node = &LogicNode{Input: &input} // 注意,接口是指针类型
    node.Run()
    x := reflect.ValueOf(node).Elem().FieldByName("Input")
    x.Set(reflect.ValueOf(&input2))
    node.Run()
}

输出结果:

Input1 = false (0x10500168)
Input2 = true (0x10500170)
LogicNode.Input = false (0x10500168)
LogicNode.Input = true (0x10500170)

Playground链接在这里

英文:

You can use the Set generic version to update the field value:

package main

import (
	&quot;fmt&quot;
	&quot;reflect&quot;
)

type LogicNode struct {
    Input   *bool
    Output   *bool
    Operator string
    Next     Node
}

func (n *LogicNode) Run() {
    // do some stuff here
    // n.Next.Run()
    fmt.Printf(&quot;LogicNode.Input = %v (%v)\n&quot;, *n.Input, n.Input)
}

type Node interface {
    Run()
}

func main() {
	input := false
	input2 := true
	fmt.Printf(&quot;Input1 = %v (%v)\n&quot;, input, &amp;input)
	fmt.Printf(&quot;Input2 = %v (%v)\n&quot;, input2, &amp;input2)
	var node Node = &amp;LogicNode{Input: &amp;input} // Remember, interfaces are pointers
	node.Run()
	x := reflect.ValueOf(node).Elem().FieldByName(&quot;Input&quot;)
	x.Set(reflect.ValueOf(&amp;input2))
	node.Run()
}

Outputs:

Input1 = false (0x10500168)
Input2 = true (0x10500170)
LogicNode.Input = false (0x10500168)
LogicNode.Input = true (0x10500170)

Playground here.

huangapple
  • 本文由 发表于 2014年1月27日 19:17:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/21379466.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定