
把两个文件的AST压成一个SHA-256摘要然后说“相似度85%”中间缺了一整套定义。哈希能回答特定表示是否相同不能直接回答相似程度更不能判断代码许可是否合规。先给“骨架”一个小而明确的定义下面只取函数名、参数个数和结果个数。它忽略函数体、注释和变量名因此相同摘要只表示这几个字段相同。这样的摘要适合做粗筛或提醒不适合当成代码来源证明。package main import ( crypto/sha256 fmt go/ast go/parser go/token strings ) func arity(f *ast.FieldList) int { if f nil { return 0 } n : 0 for _, field : range f.List { if len(field.Names) 0 { n } else { n len(field.Names) } } return n } func skeleton(src string) ([32]byte, error) { f, err : parser.ParseFile(token.NewFileSet(), sample.go, src, 0) if err ! nil { return [32]byte{}, err } var b strings.Builder for _, decl : range f.Decls { if fn, ok : decl.(*ast.FuncDecl); ok { fmt.Fprintf(b, %s:%d:%d;, fn.Name.Name, arity(fn.Type.Params), arity(fn.Type.Results)) } } return sha256.Sum256([]byte(b.String())), nil } func main() { a, e1 : skeleton(package p; func Add(a,b int) int {return ab}) b, e2 : skeleton(package p; func Add(x,y int) int {return 0}) c, e3 : skeleton(package p; func Add(x int) int {return x}) if e1 ! nil || e2 ! nil || e3 ! nil { panic(parse) } if a ! b || a c { panic(skeleton semantics) } fmt.Println(same signature, different behavior: same skeleton hash) }图示为抽象处理流程本例只取函数签名字段图中摘要是缩略符号不能作为真实校验值。两个行为明显不同的函数得到相同摘要并非SHA-256发生碰撞而是进入摘要的数据原本就一样。把丢失的信息怪到哈希算法上会让改进方向完全跑偏。如果真的需要相似检索需要先定义特征、归一化方式、相似度以及误报漏报成本。MinHash通常用来估计集合相似度仍需说明集合如何构造不能用一个函数名就替代完整方法。还需要带人工标签的样本才能讨论阈值是否有用。许可判断则是另一件事。发现候选片段后应核对上游仓库、提交、许可证和使用方式。GitHub对代码引用的说明也没有把引用索引描述成所有公开代码的完整集合。没有命中不等于不存在来源有命中也不能跳过许可义务。这个程序仅验证了“摘要反映所选表示”的边界没有实现MinHash、抄袭检测或法律判断。给小工具一个准确名字往往比给它一个夸张阈值更能帮助使用者。参考Go parserGitHubCopilot与代码引用边界