Go 为什么大的INTAPI会变得如此奇怪?

Go 为什么大的INTAPI会变得如此奇怪?,go,biginteger,Go,Biginteger,我正在努力理解设计背后的决定 例如,要添加两个大整数,必须: a := big.NewInt(10) b := big.NewInt(20) c := big.NewInt(0) d := c.Add(a,b) 其中,d在末尾与c相同。最初的零一点也不重要 为什么不只是: a := big.NewInt(10) b := big.NewInt(20) c := big.Add(a,b) 或者更好: a := big.NewInt(10) b := big.NewInt(20) c := a.

我正在努力理解设计背后的决定

例如,要添加两个大整数,必须:

a := big.NewInt(10)
b := big.NewInt(20)
c := big.NewInt(0)
d := c.Add(a,b)
其中,d在末尾与c相同。最初的零一点也不重要

为什么不只是:

a := big.NewInt(10)
b := big.NewInt(20)
c := big.Add(a,b)
或者更好:

a := big.NewInt(10)
b := big.NewInt(20)
c := a.Add(b)

他们选择这样做有什么原因吗?我发现它有点让人困惑,每当我使用它的时候,我都必须查找它。

Add
是一种改变接收器的方法

那就这么做吧

c := big.NewInt(0).Add(a,b)

Add返回receiver对于函数链接很有用,但不需要使用返回的值

现在假设我们没有一个bigInt作为接收器(
c:=big.Add(a,b)
),或者接收器不会被修改(
c:=a.Add(b)
)。在这两种情况下,只需为操作分配一个大Int并返回(作为指针)。这将是浪费的情况下,你还没有一个大整数分配和准备。计算的整数不仅仅是一个简单的一两个单词的结构,它还可以很大。所以最好使用预定义的var,特别是当你经常在计算循环的中间使用你的大整数时,

c := big.Add(a,b) // wasteful because doesn't allow the use of a preexisting big int

c := a.Add(b) // either modifies a (which would force you to copy it each time if you want to keep it) or is wasteful like the last one

<>我将添加丹尼斯的答案,如果你考虑替代API,它可以支持链接如下:

x.Add(y).Add(z).Mul(v) 
很快,问题是——这是否遵守正常的操作员命令

x+y+z*v = x+y+(z*v) 
但是第一条链将导致(x+y+z)*v(在go中,但可能不是在另一种语言中)-因此需要小心

这:

有点难看,我同意,但它确实强制执行显式顺序,而且它还让我们有机会保持操作数不变,而无需额外分配(如Denys所述)。e、 g.(每次通知r为接收人):

这里只更改了结果值(r),x、y、z保持不变-要在第一种样式的API中执行此操作,每次都需要分配。因此,在这种情况下,要么对操作数进行变异,要么在big.Int api中进行分配,您可以选择其中之一

顺便说一句,以下内容相当于第一个链接

r = r.Mul(r.AddP(x, r.Add(y, z)), v) 

它实际上看起来更像(x+y+z)*v

我知道我不需要使用返回值。但是为什么需要第三个大的.Int作为接收器呢?请参见编辑:接收器很有用,因为它允许使用现有的结构。与例如GMP的模式相比:
mpz\u foo(mpz\u t*rop,mpz\u t*op1,mpz\u*op2)
。这就像围棋中的
rop.Foo(op1,op2)
。@kugel当然。对于这样一个库,性能非常重要。
r = r.AddP(x, y.Add(y, z.Mul(z, v)))
r = r.Add(x, r.Add(y, r.MulInt(z, v)))
r = r.Mul(r.AddP(x, r.Add(y, z)), v)