gpt4 book ai didi

variables - 初始化自定义类型不适用于 var,但适用于 :=

转载 作者:行者123 更新时间:2023-12-02 18:59:45 27 4
gpt4 key购买 nike

我正在尝试初始化 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:无法在赋值中使用 x(类型 float64)作为 ErrNegativeSqrt 类型

为什么会发生这种情况?是不是和:=赋值一样?

Here there is the playground.

最佳答案

在此variable declaration :

var err ErrNegativeSqrt = x

您显式赋予 err 类型 ErrNegativeSqrt,并尝试将 x 分配给它,但 x其类型为 float64,不可分配给 ErrNegativeSqrt 类型的值。 Assignability规则不适用, float64ErrNegativeSqrt 是两种不同的、不同的类型(尽管后者将前者作为其 underlying type ,所以它们是 convertible 彼此)。

当您使用此short variable declaration时:

err := ErrNegativeSqrt(x)

您明确convert xErrNegativeSqrt,因此 x 的类型将被推断为 ErrNegativeSqrt

您可以在使用 var 关键字时执行相同的操作:

var err ErrNegativeSqrt = ErrNegativeSqrt(x)

或者简单地说:

var err = ErrNegativeSqrt(x)

这正是 short variable declaration 的内容是缩写形式。

注释

如前所述,var err ErrNegativeSqrt = x 无效,因为 assignability规则不适用:

A value x is assignable to a variable of type T ("x is assignable to T") if one of the following conditions applies:

  • x's type is identical to T.
  • x's type V and T have identical underlying types and at least one of V or T is not a defined type.
  • T is an interface type and x implements T.
  • x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type.
  • x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
  • x is an untyped constant representable by a value of type T.

正如您所看到的,第二条规则“几乎”涵盖了我们想要在这里做的事情:

x's type V and T have identical underlying types and at least one of V or T is not a defined type

之所以“几乎”是因为 ErrNegativeSqrtfloat64 都是命名的 ( defined ) 类型。

当你这样做时:

var err ErrNegativeSqrt = 1.0

这之所以有效,是因为您在这里分配了一个非类型化 constant 1.0 可以在需要时采用所需的类型(如上面的作业)。由于您要分配给 ErrNegativeSqrt 类型的 err,因此无类型常量 1.0 可以采用 ErrNegativeSqrt 类型(因为 ErrNegativeSqrt 的基础类型是 float64,而 1.0 是无类型浮点常量)。这种情况正是最后一个可分配性规则:

x is an untyped constant representable by a value of type T.

如果你愿意:

var err ErrNegativeSqrt = float64(1.0) // FAIL!!

正如您在问题中的示例一样,这将再次失败,因为这里我们使用类型化常量,它不能任意更改类型,没有可分配性规则允许这样做。

阅读博客文章 The Go Blog: Constants了解常量在 Go 中如何工作的更多详细信息。

关于variables - 初始化自定义类型不适用于 var,但适用于 :=,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58874864/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com