【问题标题】:Reference type confusing in Go languageGo 语言中的引用类型令人困惑
【发布时间】:2015-02-26 07:48:12
【问题描述】:

我试图用 Go 语言制作 Trie 数据结构,但不知何故它遇到了引用问题, 这里是。 http://play.golang.org/p/ASSGF5Oe9R

// Package main provides ...
package main

import "fmt"

type RootTrie []Trie

type Trie struct {
    subtrie []Trie
    index   byte
}

func (trie *Trie) Insert(data string) *Trie {
    if data != "" {
        if trie.index == 0 {
            trie.index = data[0]
        }
        if next := trie.containsIndex(data[1:]); next != nil {
            //Problem Point
            fmt.Println(string(data[1]), "found follwing", string(data[0]))
            next.Insert(data[1:])
        } else {
            nt := &Trie{}
            trie.subtrie = append(trie.subtrie, *nt.Insert(data[1:]))
        }
    }

    return trie
}
func (trie *Trie) containsIndex(next string) *Trie {
    if next != "" {
        for _, st := range trie.subtrie {
            if st.index == next[0] {
                return &st
            }
        }
    }
    return nil
}

func main() {
    t := &Trie{}
    t = t.Insert("hanyang")
    fmt.Println("result:", t)
    t = t.Insert("hanyKk")
    fmt.Println("result:", t)
    t.Insert("hanyK")
}

在第二个“插入”中出现以下问题, 我放的地方,//Problem Point

我制作了containsIndex 方法来搜索下一个链接的trie,它实际上搜索得很好。 但是当我更新containsIndex 给出的next 属性时,它并没有影响它的母结构trie

我不明白的是我在返回 containsIndex 时给了它引用类型,但它仍然 行为喜欢'价值复制',为什么它不影响其母结构(trie)?

谢谢!

【问题讨论】:

  • 我不明白 -1 - 存在语言障碍,但它解释了问题的本质,并且有代码可以乱七八糟。

标签: go pass-by-reference pass-by-value trie pass-by-name


【解决方案1】:

问题出在方法 containsIndex 中。 Golang range 默认情况下会在 slice 中创建每个元素的副本,并将该值的副本分配给 st (在您的示例中)。通常要保留对切片中元素的引用,您应该使用原始切片及其索引。在您的情况下,方法 containsIndex 应该如下所示:

func (trie *Trie) containsIndex(next string) *Trie {
    if next != "" {
        for i, st := range trie.subtrie {
            if st.index == next[0] {
                return &trie.subtrie[i]
            }
        }
    }
    return nil
}

【讨论】:

  • 这是否也意味着仅使用索引而不是值时的性能差异?
  • @EtienneBruines——也许吧。它可能可以忽略不计,或者如果编译器认识到它有时可以优化副本,则可能没有区别。如果您在性能关键的内部循环中遇到这种选择,您可以随时进行测试。
  • @twotwotwo 感谢您的回复。我运行了一些基准测试:在不复杂的情况下,根本没有性能差异。 github.com/EtienneBruines/go-range-performance-analysis
  • 谢谢,@wonsky。我在那里找到了一些有趣的答案,我检查了地址差异link
猜你喜欢
  • 2012-09-12
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多