Go FAQ 回答了一个关于方法中按值与按指针接收器定义选择的问题。该答案中的陈述之一是:
如果该类型的某些方法必须有指针接收器,其余的也应该如此,因此无论如何使用该类型,方法集都是一致的。
这意味着,如果我对一个数据类型有一些改变数据的方法,因此需要按指针接收器,我应该对为该数据类型定义的所有方法使用按指针接收器。
另一方面,"fmt"包通过 value调用接口中String()定义的方法。如果用接收器按指针定义方法,则当关联的数据类型作为参数提供给(或其他格式化方法)时,将不会调用该方法。这让人们别无选择,只能使用接收器按值实现该方法。StringerString()fmt.PrintlnfmtString()
正如常见问题解答所建议的那样,在满足接口fmt要求的同时,如何与按值与按指针的选择保持一致Stringer?
编辑:
为了强调我提到的问题的本质,考虑一个数据类型,其中包含一组用接收者按值定义的方法(包括 String())。然后一个人希望添加一个额外的方法来改变该数据类型 - 所以他用接收者按指针定义它,并且(为了保持一致,每个常见问题解答)他还更新了该数据类型的所有其他方法以供使用- 指针接收器。此更改对使用此数据类型方法的任何代码的影响为零 - 但用于调用fmt格式化函数(现在需要将指针传递给变量而不是其值,就像更改之前一样)。因此,一致性要求仅在fmt. 需要调整提供变量的方式fmt.Println (或类似功能)基于接收器类型打破了轻松重构一个包的能力。
我正在尝试在 LLVM 传递中使用由llvm::Module::getFunctionList(). 我使用这样的循环:
for (auto curFref = M->getFunctionList().begin(),
endFref = M->getFunctionList().end();
curFref != endFref; ++curFref) {
errs() << "found function: " << curFref->getName() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这个循环的第一次迭代按预期检索一个函数,但它没有检测到列表的末尾,而是继续在后续迭代中获取不是函数的其他对象(如它们的 报告getName()),例如该函数参数。经过几次迭代后,它可能会达到一些垃圾(或 NULL)并在引用当前“函数”引用时崩溃。例如,对于这个程序:
int foo(int k) {
int i, s = 0;
for (i = 0; i < k; ++i)
s += i;
return s;
}
Run Code Online (Sandbox Code Playgroud)
这变成了这个 IR 代码:
...
; Function Attrs: nounwind uwtable
define i32 @foo(i32 %k) #0 {
entry:
...
Run Code Online (Sandbox Code Playgroud)
输出将如下所示:
found function: foo
found function: …Run Code Online (Sandbox Code Playgroud)