Go语言-类型推断解析[1]

357次阅读  |  发布于2年以前

Don’t do it. Do it, but don’t do it again. Do it less. Do it later. Do it when they’re not looking. Do it concurrently. Do it cheaper.

类型推断(Type Inference)是编程语言在编译时自动解释表达式中数据类型的能力,通常在函数式编程的语言(例如Haskell)中存在。类型推断的优势主要在于可以省略类型,这使编程变得更加容易。

明确地指出变量的类型在编程语言中很常见,编译器在多大程度上支持类型推断因语言而异。例如,某些编译器可以推断出变量、函数参数和返回值的类型。如图所示,Go语言提供了特殊的操作符“:=”用于变量的类型推断。

图 :=操作符用于变量类型推断

类型推断的优势

语言支持类型推断有两个主要的优势。一是如果使用得当,那么它可以使代码更易阅读。例如,可以将C ++代码

vector<int> v;
vector<int>::iterator itr = v.iterator();

变为

vector<int> v;
auto itr = v.iterator();

二是如果类型更加复杂,那么类型推断的价值变得显而易见。在许多情况下,这将减少代码中的冗余信息。

类型推断还具有动态语言的灵活特性,例如Haskell语言的如下代码,不管变量x是什么类型,加1并返回结果。

succ x = x + 1

尽管如此,显式地指出类型仍可以让编译器更轻松地了解代码实际应执行的操作,而不会犯任何错误。

Go语言中类型推断的特性

如上所述,每个语言的类型推断能力是不相同的,Go语言的目标是减少在其他静态类型语言中存在的混乱情况,Go语言的设计者认为Java或C++中的类型系统过于复杂。因此,在设计Go语言时,他们对变量使用简单的类型推断,给人以编写动态类型代码的感觉,同时仍然保留静态类型的好处。

Go语言的类型推断目前还相对简单,没有涵盖参数和返回值之类的内容。在实践中,可以通过在声明新变量或常量时忽略类型信息或使用:=表示法来触发Go语言中的类型推断。例如,在Go语言中,以下三个语句是等效的。

var a int = 10
var a = 10
a := 10

以a := 333为例,变量a最终会被推断为int类型,可以用Printf 的%T格式化打印出a的类型,输出结果为type:int。

a :=  333
fmt.Printf("type:%T",a)

由于Go语言的类型系统禁止了不同类型之间的转换(第4章中的常量除外),由于下例中的a已经被推断为int类型,不能够赋值给int64 类型。

func main() {
    a:=333
    var b int64
    b = a
}

Go语言的类型推断在处理包含变量标识符的推断方面是半智能的。本质上,编译器不允许对变量标识符引用的值进行强制类型转换,举几个例子:

下面这段代码能够正常运行,并且a的类型为float64。

a := 1 + 1.1

下面的代码仍然正确,a会被推断为浮点数,1会被转换为浮点数与a的值相加。

a := 1.1
b := 1 + a

但是,下面代码是错误的,即a的值已被推断为整数,而1.1为浮点数,不能将a强制转换为浮点数,相加失败。编译器报错:constant 1.1 truncated to integer。

a := 1
b := a + 1.1

下面的例子犯了相同的错误,编译器提示类型不匹配:invalid operation: a + b (mismatched types int and float64)。

a := 1
b := 1.1
c := a + b

在下一篇文章中,将介绍类型推断的原理,see you~

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8