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

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

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

问题

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

请参考我的问题的注释:

  1. type LogicNode struct {
  2. Input *bool
  3. Output *bool
  4. Operator string
  5. Next Node
  6. }
  7. func (n *LogicNode) Run() {
  8. // 在这里做一些事情
  9. n.Next.Run()
  10. }
  11. type Node interface {
  12. Run()
  13. }
  14. func main() {
  15. nodes := make([]Node, 1000)
  16. for i := 0; i < 1000; i++ {
  17. n := LogicNode{
  18. // 分配值等等。
  19. }
  20. nodes[i] = &n
  21. }
  22. for i, node := range nodes {
  23. // 我需要在这里访问LogicNode的Output指针,作为*bool类型。
  24. // 这样我就可以将相同的地址设置给其他Node的Input,从而"连接"它们。
  25. // 但是我只能得到类似这样的东西:
  26. x := reflect.ValueOf(node).Elem().FieldByName("Output")
  27. // 它是<*bool Value>
  28. // 我找不到一种方法来将一个新的*bool设置到底层(LogicNode)结构的Input或Output中...
  29. }
  30. }

我使用接口的原因是因为还有其他节点类型,如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:

  1. type LogicNode struct {
  2. Input *bool
  3. Output *bool
  4. Operator string
  5. Next Node
  6. }
  7. func (n *LogicNode) Run() {
  8. // do some stuff here
  9. n.Next.Run()
  10. }
  11. type Node interface {
  12. Run()
  13. }
  14. func main() {
  15. nodes := make([]Node, 1000)
  16. for i := 0; i &lt; 1000; i++ {
  17. n := LogicNode{
  18. //assign values etc.
  19. }
  20. nodes[i] = &amp;n
  21. }
  22. for i, node := range nodes {
  23. // I need to access LogicNode&#39;s Output pointer here, as a *bool.
  24. // so I can set the same address to other Node&#39;s Input thereby &quot;connecting&quot; them.
  25. // but I could only get something like this:
  26. x := reflect.ValueOf(node).Elem().FieldByName(&quot;Output&quot;)
  27. // which is &lt;*bool Value&gt;
  28. // I couldn&#39;t find a way to set a new *bool to the underlying (LogicNode) Struct&#39;s Input or Output..
  29. }
  30. }

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泛型版本来更新字段的值:

  1. package main
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. type LogicNode struct {
  7. Input *bool
  8. Output *bool
  9. Operator string
  10. Next Node
  11. }
  12. func (n *LogicNode) Run() {
  13. // 在这里做一些操作
  14. // n.Next.Run()
  15. fmt.Printf("LogicNode.Input = %v (%v)\n", *n.Input, n.Input)
  16. }
  17. type Node interface {
  18. Run()
  19. }
  20. func main() {
  21. input := false
  22. input2 := true
  23. fmt.Printf("Input1 = %v (%v)\n", input, &input)
  24. fmt.Printf("Input2 = %v (%v)\n", input2, &input2)
  25. var node Node = &LogicNode{Input: &input} // 注意,接口是指针类型
  26. node.Run()
  27. x := reflect.ValueOf(node).Elem().FieldByName("Input")
  28. x.Set(reflect.ValueOf(&input2))
  29. node.Run()
  30. }

输出结果:

  1. Input1 = false (0x10500168)
  2. Input2 = true (0x10500170)
  3. LogicNode.Input = false (0x10500168)
  4. LogicNode.Input = true (0x10500170)

Playground链接在这里

英文:

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

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;reflect&quot;
  5. )
  6. type LogicNode struct {
  7. Input *bool
  8. Output *bool
  9. Operator string
  10. Next Node
  11. }
  12. func (n *LogicNode) Run() {
  13. // do some stuff here
  14. // n.Next.Run()
  15. fmt.Printf(&quot;LogicNode.Input = %v (%v)\n&quot;, *n.Input, n.Input)
  16. }
  17. type Node interface {
  18. Run()
  19. }
  20. func main() {
  21. input := false
  22. input2 := true
  23. fmt.Printf(&quot;Input1 = %v (%v)\n&quot;, input, &amp;input)
  24. fmt.Printf(&quot;Input2 = %v (%v)\n&quot;, input2, &amp;input2)
  25. var node Node = &amp;LogicNode{Input: &amp;input} // Remember, interfaces are pointers
  26. node.Run()
  27. x := reflect.ValueOf(node).Elem().FieldByName(&quot;Input&quot;)
  28. x.Set(reflect.ValueOf(&amp;input2))
  29. node.Run()
  30. }

Outputs:

  1. Input1 = false (0x10500168)
  2. Input2 = true (0x10500170)
  3. LogicNode.Input = false (0x10500168)
  4. 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:

确定