起因是在写一个函数的时候
func (g *Grammar) extractCommonFactors() {
flag := false
newNonTerminalCounter := 0
for i, production := range g.Productions {
newAlternatives := []Alternative{}
prefixMap := make(map[Symbol][]Alternative)
for _, alternative := range production.Right {
if len(alternative.Symbols) > 0 {
firstSymbol := alternative.Symbols[0]
if _, ok := prefixMap[firstSymbol]; !ok {
prefixMap[firstSymbol] = []Alternative{}
}
prefixMap[firstSymbol] = append(prefixMap[firstSymbol], alternative)
}
}
for _, alternatives := range prefixMap {
if len(alternatives) > 1 {
flag = true
commonPrefix := findLongestCommonPrefix(alternatives)
newNonTerminalCounter++
newValue := fmt.Sprintf("A%d", newNonTerminalCounter)
newNonTerminal := Symbol{
Value: newValue,
IsTerminal: false,
}
newRight := removeCommonPrefix(alternatives, commonPrefix)
newProduction := Production{
Left: newNonTerminal,
Right: newRight,
}
g.Productions = append(g.Productions, newProduction)
var newAlternative Alternative
newAlternative.Symbols = commonPrefix
//bug出现的地方
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal)
newAlternatives = append(newAlternatives, newAlternative)
} else {
newAlternatives = append(newAlternatives, alternatives[0])
}
}
g.Productions[i].Right = newAlternatives
}
if flag {
fmt.Println("extractCommonFactors grammar:")
for _, prod := range g.Productions {
rightParts := make([]string, len(prod.Right))
for i, alt := range prod.Right {
symbols := make([]string, len(alt.Symbols))
for j, sym := range alt.Symbols {
symbols[j] = sym.Value
}
rightParts[i] = strings.Join(symbols, "")
}
fmt.Printf("%s -> %s\n", prod.Left.Value, strings.Join(rightParts, "|"))
}
}
}
发现每次在执行
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal)
时总会莫名其妙修改掉g.Productions 中的数据
原因就是因为
var newAlternative Alternative
newAlternative.Symbols = commonPrefix
//bug出现的地方
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal)
中的newAlternative.Symbols是一个数组切片,这里直接对切片赋值,本质上是将newAlternative.Symbols的内容修改为commonPrefix切片所指向的数组,所以后续在修改newAlternative.Symbols时对别的内容也会产生影响
改正为
var newAlternative Alternative
commonPrefixCopy := make([]Symbol, len(commonPrefix))
copy(commonPrefixCopy, commonPrefix)
newAlternative.Symbols = commonPrefixCopy
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal)
之后问题就消失了
因为copy函数是在内存中开辟一个新的数组给复制的切片使用,这样虽然消耗了更多的内存,但也更安全,是个更好的开发习惯
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。