将Golang定义的类型视为基础类型?

时间:2019-06-06 02:08:30

标签: go types polymorphism

我是Golang的新手。我了解如下定义新类型的基本知识:

type MyCondition bool

我知道这意味着,无论何时我声明一个函数接受一个MyCondition的实例,它都不能是bool,这很好。但是,我想将MyCondition的实例视为bool的实例,但我发现我不能总是这样做:

package main

import (
    "fmt"
)

type MyCondition bool

func main() {
    var b1 MyCondition
    var b2 = true
    fmt.Println(!b1) // OK!
    fmt.Println(b1 || b1) // OK
    fmt.Println(b1 || b2)
}

无法编译,抛出:

./prog.go:13:17: invalid operation: b1 || b2 (mismatched types MyCondition and bool)

从我观察到的情况来看,MyCondition本身就是一个布尔对象,但是当我将其与实际的bool“混合”时会出现问题。

问题是:

  1. 为什么会这样?
  2. 有什么解决方法?我真的很想把它像布尔一样对待,而无需多态铸造。

3 个答案:

答案 0 :(得分:4)

您不能那样做。您必须将MyCondition明确转换为bool,即bool(b1) || b2

来自Go spec

  

逻辑运算符适用于布尔值,并产生与操作数相同类型的结果。

如果左操作数和右操作数具有不同的类型,则编译器无法确定结果类型。因此,这两个操作数必须具有相同的类型。

答案 1 :(得分:2)

  

1。为什么会这样?

Go是强类型语言。因此,这是设计使然。这样可以确保代码正确性,并且绝对可以排除某些类型的编程错误。

  
      
  1. 有什么解决方法?我真的很想把它像布尔一样对待,而无需多态铸造。
  2.   

解决方法:
1.如果不需要好处,请不要使用新的命名类型,而应使用bool
2.使用类型转换,例如bool(b1)MyCondition(b2)适当。
3.使用“方法集”适当地转换或执行更多工作。
4.使用Go类型alias(自Go 1.9起):type MyCondition = bool

当您为bool使用新的类型名称时,您要求编译器 strong 检查类型和此类编程错误。因此,如果不需要此类编译器帮助,请不要使用新的命名类型,而只需使用bool

在这里要注意有关Method sets及其用法:

您可以使用新方法,例如ToBool进行这种类型转换,如果需要,还可以尝试更多操作,请尝试this

package main

import "fmt"

type MyCondition bool

func (c MyCondition) ToBool() bool {
    return bool(c)
}

func main() {
    var b1 MyCondition
    var b2 = true
    fmt.Println(b2)  // true
    b2 = b1.ToBool() // b1.bool()
    fmt.Println(b2)  // false
}

相关参考文献:

类型Conversion

  

转换将表达式的类型更改为指定的类型   通过转换。转换可能会原样出现在源中,或者   表达式出现的上下文可能暗示了这一点。

     

显式转换是形式为T(x)的表达式,其中T是一个   类型,并且x是可以转换为T类型的表达式。

Conversion = Type "(" Expression [ "," ] ")" .

Type assertions用于界面类型。

Type identity

Alias declarations

答案 2 :(得分:-1)

您可以使用别名(注意类型定义)作为解决方法,但是在这种情况下,您将无法保证类型的安全性。

package main

import (
    "fmt"
)

type MyCondition = bool

func main() {
    var b1 MyCondition
    var b2 = true
    fmt.Println(!b1) // OK!
    fmt.Println(b1 || b2)
    fmt.Println(foo(b2))
}

func foo(b MyCondition) bool {
    return !b
}