Go 语言中的引用类型令人困惑

Posted

技术标签:

【中文标题】Go 语言中的引用类型令人困惑【英文标题】:Reference type confusing in Go language 【发布时间】: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 - 存在语言障碍,但它解释了问题的本质,并且有代码可以乱七八糟。 【参考方案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

以上是关于Go 语言中的引用类型令人困惑的主要内容,如果未能解决你的问题,请参考以下文章

Go语言之GO 语言引用类型

go语言关于值类型和引用类型

go语言学习笔记 — 基础 — 基本数据类型 — 类型类别:值类型和引用类型

《Go语言实战》Go 类型:基本类型引用类型结构类型自定义类型

Go语言引用类型

Java与Go语言差异1 传值还是传引用