http://play.golang.org/p/Vd3meom5VF
我在Go
中有一些上下文无关语法的代码我正在看这段代码很多次,但仍然没有看到任何改变struct值的原因。有人能看出为什么会发生以下变化吗?
规则:
S - > 。 [DP VP]
VP - > 。 [V DP]
VP - > 。 [V DP AdvP]
我在行中运行了一些函数
or2 = append(or2, OstarCF([]QRS{q}, []string{"sees"}, g2.Nullables(), g2.ChainsTo(g2.Nullables()))...)
不知怎的,我的结构值发生了变化......我不知道为什么......
规则:
S - > 。 [VP VP]
VP - > 。 [DP DP]
VP - > 。 [AdvP AdvP AdvP]
这应与上述相同。
Rules:
S -> DP,VP
VP -> V,DP
VP -> V,DP,AdvP
or2 := []QRS{}
g2 := ToGrammar(cfg2)
fmt.Printf("%s\n", g2)
for _, rule := range g2.Rules {
q := QRS{
one: rule.Src,
two: []string{},
three: rule.Right,
}
or2 = append(or2, OstarCF([]QRS{q}, []string{"sees"}, g2.Nullables(), g2.ChainsTo(g2.Nullables()))...)
}
fmt.Printf("%s\n", g2)
如您所见,我没有使用任何指针变量规则,它们仅用于实例化另一个结构值,但原始结构字段规则如何已经改变?函数OstarCF对此字段规则
没有任何作用 func OstarCF(Qs []QRS, R []string, nD map[string]bool, cD map[string][]string) []QRS {
symbols := []string{}
for _, r := range R {
symbols = append(symbols, cD[r]...)
}
product := []QRS{}
for _, Q := range Qs {
a := Q.one
b := Q.two
c := Q.three
if len(c) > 0 && CheckStr(c[0], symbols) {
b = append(b, c[0])
np := QRS{
one: a,
two: b,
three: c[1:],
}
product = append(product, np)
for len(np.three) > 0 && nD[np.three[0]] == true {
np.two = append(np.two, np.three[0])
np = QRS{
one: np.one,
two: np.two,
three: np.three[1:],
}
product = append(product, np)
}
}
}
return product
}
答案 0 :(得分:2)
原始规则字段更改,因为使用了指针和切片(也是引用)。
在调用OstarCF之前,调用ChainsTo方法。它按值使用语法对象,因此复制完成,但规则字段是规则上的一个指针片。因此,当复制此字段时,它仍然指向原始对象的数据。
然后,在方法ChainsTo中,Rules字段上有一个循环。它复制了Right字段,它是一个字符串片段(因此它仍然指向原始对象的数据):
rhs := rule.Right
最后,通过切片rhs:
声明一个ns变量ns := rhs[:i]
ns = append(ns, rhs[i+1:]...)
在此阶段,ns变量仍指向包含原始对象的字符串切片的缓冲区。最初,i = 0,因此ns是重用缓冲区的空切片。附加项目后,它们将替换原始数据。
这就是您的数据发生变化的原因。
您可以通过显式制作副本来解决此问题,例如将上述行替换为:
ns := make( []string, 0, len(rhs) )
ns = append( ns, rhs[:i]...)
ns = append( ns, rhs[i+1:]...)
Go切片已经取代了C指针算法,但在某些情况下它们几乎可以像危险/误导一样。