在Go语言中,原始值的typedef是等效的吗?

huangapple go评论87阅读模式
英文:

Are typedefs for primitive values equivalent in golang?

问题

给定这段代码:

type Philosopher int
const (
    Epictetus Philosopher = iota
    Seneca
)

func Quote(who Philosopher) string {
    fmt.Println("t: ", reflect.TypeOf(who))
    switch who {
    case Epictetus:
        return "First say to yourself what you would be; and do what you have to do"
    case Seneca:
        return "If a man knows not to which port he sails, No wind is favorable"
    }
    return "nothing"
}

调用 Quote(5) 将打印出类型为 Foo.Philosopher 的结果。
为什么类型检查器没有报错呢?因为类型安全的枚举应该限制值的范围。

英文:

Given this code:

type Philosopher int
const (
    Epictetus Philosopher = iota
    Seneca
)

func Quote(who Philosopher) string {
    fmt.Println("t: ", reflect.TypeOf(who))
    switch who {
    case Epictetus:
        return "First say to yourself what you would be; 
                and do what you have to do"
    case Seneca:
        return "If a man knows not to which port he sails, 
                No wind is favorable"
    }
    return "nothing"
}

Calling Quote(5) will print Foo.Philosopher as the type for 5.
Why didn't the type checker complain since that is what a type safe enums are supposed to do i.e. limit the scope of values ?

答案1

得分: 9

这些并不是你所认为的枚举类型。Philosopher 类型更多地是 int 的别名。更准确地说,它是一种基本不同的类型,可以定义自己的方法。

它的目的是以一种对程序员来说清晰明了的方式提供常量的语义分组。此外,在编译时,你可以享受到 Go 的类型检查器的好处。但是只有在将值传递给 func(Philosopher) 时,才能确保参数不能被隐式解释为其他类型。传递字面量 5 作为参数是可以的,因为在 Go 中这样的常量本质上是无类型的。但是下面的代码将无法通过编译:

n := 5
Quote(n)  // 编译错误 -> int 不是 Philosopher

原因是 n 被定义为 int 类型。int 类型和 Philosopher 类型之间不存在隐式转换。然而,下面的代码可以通过编译:

n := 5
Quote(Philosopher(n))

因为类型转换是有效的。Go 不关心 5 是否是一个有效且预定义的 Philosopher 常量。

英文:

These are not enums as you think of them. Type Philosopher is more or less an alias of an int. More or less, because it is a fundamentally distinct type, which can define its own methods.

The point of it is to provide semantic grouping of constants in a way that is clear to the programmer. Additionally, one gets the benefit of Go's type checker during compile time. But only to the degree that a value passed into a func(Philosopher) can not be implicitly interpreted as such. Passing a literal 5 as the parameter works, because constants like that in Go are inherently untyped. This will not work;

n := 5
Quote(n)  // Compile error -> int is not Philosopher

Reason being that n is defined as int. There exists no implicit conversion between type int and Philosopher. However, this will work:

n := 5
Quote(Philosopher(n))

Because the type cast is valid. Go does not care whether or not 5 is a valid and pre-defined Philosopher constant.

答案2

得分: 1

Go对有效值没有任何保证,除了int所暗示的值。使用iota只是为了方便定义一系列常量;它并不表示任何关于有效值的信息。

5是一个有效的int,因此也是一个有效的Philosopher。你也可以创建const Plato = Philosopher(5)。

英文:

Go doesn’t make any guarantees about valid values, except for those implied by int. The use of iota is just a convenience for defining a series of constants; it doesn’t say anything about valid values.

5 is a valid int, and therefore a valid Philosopher. You could also create const Plato = Philosopher(5).

答案3

得分: 1

更简短的答案应该是:未类型化的常量会根据其上下文需要的类型进行推断。

英文:

Shorter answer should be like :

> An untyped constant takes the type needed by its context.

huangapple
  • 本文由 发表于 2014年3月18日 05:11:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/22465501.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定