我正在尝试初始化ErrNegativeSqrt,它是自定义的float64类型,但是如果我使用var
进行操作,将无法正常工作。
看看func Sqrt(x float64) (float64, error)
:
package main
import (
"fmt"
)
type ErrNegativeSqrt float64
func (e *ErrNegativeSqrt) Error() string {
return fmt.Sprint("cannot Sqrt negative number: %f", float64(*e))
}
func Sqrt(x float64) (float64, error) {
if x < 0 {
var err ErrNegativeSqrt = x
// This works: err := ErrNegativeSqrt(x)
return x, &err
}
z := x / 2
i := 1
for prev_z := 0.0; z != prev_z && Abs(z-prev_z) > 0.000000000000001; i++ {
prev_z = z
z -= (z*z - x) / (2 * z)
}
return z, nil
}
func Abs(x float64) float64 {
if x < 0 {
x = -x
}
return x
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
错误是:./prog.go:15:7: cannot use x (type float64) as type ErrNegativeSqrt in assignment
为什么会发生?是不是和:=
的分配相同?
答案 0 :(得分:5)
var err ErrNegativeSqrt = x
您为err
明确指定了ErrNegativeSqrt
类型,并尝试为其分配x
,但是x
属于float64
类型,无法分配设置为ErrNegativeSqrt
类型的值。 Assignability规则不适用,float64
和ErrNegativeSqrt
是2种不同的不同类型(尽管后者以underlying type为前者,所以它们是{{3} })。
使用此convertible时:
err := ErrNegativeSqrt(x)
您将short variable declaration x
显式地转换为ErrNegativeSqrt
,因此x
的类型将被推断为ErrNegativeSqrt
。
使用var
关键字时,您可以这样做:
var err ErrNegativeSqrt = ErrNegativeSqrt(x)
或者简单地:
var err = ErrNegativeSqrt(x)
convert的缩写正是。
如前所述,var err ErrNegativeSqrt = x
无效,因为short variable declaration规则不适用:
如果满足以下条件之一,则值
x
可分配给类型T
的{{3}}(“x
可分配给T
”) :
x
的类型与T
相同。x
的类型V
和T
具有相同的assignability,并且V
或T
中的至少一个不是{{ 3}}类型。T
是接口类型,并且是x
variableT
。x
是双向通道值,T
是通道类型,x
的类型V
和T
具有相同的元素类型,并且在V
或T
中至少有一个不是已定义的类型。x
是预先声明的标识符nil
,而T
是指针,函数,切片,映射,通道或接口类型。x
是类型为T
的值的无类型underlying types defined。
如您所见,第二条规则“几乎”涵盖了我们在此处要做的事情:
x
的类型V
和T
具有相同的基础类型,并且V
或T
中的至少一个不是已定义类型
之所以“几乎”是因为ErrNegativeSqrt
和float64
都被命名为(implements)类型。
当您这样做:
var err ErrNegativeSqrt = 1.0
之所以行之有效,是因为在这里您要分配一个 untyped constant 1.0
,它可以在需要时采用所需的类型(如上述分配)。由于您要分配类型为err
的{{1}},因此未类型化的常量ErrNegativeSqrt
可以采用类型1.0
(因为ErrNegativeSqrt
的基础类型为{{1 }}和ErrNegativeSqrt
是无类型的浮点常量)。这种情况恰好是最后一个可分配性规则:
float64
是类型为1.0
的值的无类型representable defined。
如果愿意的话:
x
这将再次失败,就像您在问题中的示例一样,因为在这里我们使用的是 typed 常量,该常量不能任意更改类型,没有可分配性规则允许这样做。
请阅读博客文章constant,详细了解常量在Go中的工作原理。