[奔跑的 Go] 教程三、Go 语言中的变量和常量

Golang

了解 Go 的变量数据类型,如何声明变量以及 := 符号用于类型引用的工作原理

变量 & 数据类型

什么是变量?

一个变量就是一个指定类型的存储单元。你可以给这个存储单元命名。变量定义时必须指定数据类型。例如, string 就是用于存储字符串的数据类型。

数据类型

Go 包含很多种数据类型。下面一一介绍:

类型 使用 默认值
bool 布尔类型。 值为 truefalse. false
string 字符串类型。值为 UTF-8 编码的字符串. go 中所有字符串的默认编码都是 UTF-8。与 JavaScript 不同,只有字符串可以用双引号。 空字符串
int 整型。值为 32-bit or 64-bit 的整数。 系统会为 32-bit 分配 32 个字节的内存空间,为 64-bit 分配 64 个字节的内存空间。因此,32-bit 可以存储-2147483648 到 2147483647 的数字,而 64-bit 可以存储 -9223372036854775808 到 9223372036854775807 的数字。 0
uint 整型。与 int 一样, uint 也能存储 32 个字节或 64 个字节,但是是非负值 的整数。 0
int8 整型。 系统会分配 8 个字节的内存来存储整数。因此,能够存储 -128 到 127 的数字。 0
uint8 整型。与 int8 一样,uint8 能够存储 8 个字节的 非负值 整数。 因此,它能够存储的数字是 0 到 255。 0
int16 整型。系统会为其分配 16 个字节的存储空间用于存储整数。因此,它能够存储 -32768 到 32767 的数字。 0
uint16 整型。 与 int16 一样,uint16 能够存储 8 个字节的 非负值 整数。 因此,它能够存储的数字是 0 到 65535。 0
int32 整型。 系统会分配 32 个字节的内存来存储整数。因此,能够存储 -2147483648 到 2147483647 的数字。 0
uint32 整型。 与 int32 一样,uint32 能够存储 32 个字节的 非负值 整数。 因此,它能够存储的数字是 0 到 4294967295 的数字。 0
int64 整型。 系统会分配 64 个字节的内存来存储整数。因此,能够存储 -9223372036854775808 到 922337203685477580 的数字。 0
uint64 整型。 与 int64 一样,uint64 能够存储 64 个字节的 非负值 整数。 因此,它能够存储的数字是 0 到 18446744073709551615。 0
float32 浮点型。系统会为其分配 32 个字节的内存空间用来存储浮点数。因此,它能够存储的数值是 -3.4E+38 到 +3.4E+38。 0
float64 浮点型。系统会为其分配 64 个字节的内存空间用来存储浮点数。因此,它能够存储的数值是 -1.7E+308 到 +1.7E+308。 0
complex64 Go 还支持复合数据类型。 complex64float32 的实数部分和 float32 的虚数部分构成。 0+0i
complex128 complex64 类似,complex128float64 的实数部分和 float64 的虚数部分构成。 0+0i
byte uint8 的别名。 0
rune int32 的别名。它代表一个 Unicode 字符。 0

零值

在其他编程语言中,对于未初始化的变量,系统会赋予其 null 或者 undefined,在 go 中, 则是赋给这些变量符合其数据类型的零值。参照上表,布尔类型的变量就会被赋值为 false,整形变量会被赋值为 0

声明变量

请参考下面的语法声明一个变量

var variableName dataType = initialValue

initialValue 是可选的。如果你没有赋初始值,变量就会被赋予符合其声明的数据类型的 零值

var integer1 int = 15
var integer2 int8 = -25
var integer3 int32
var float1 float32 = 63.2
var string1 string = "Hello World!"
var boolean1 bool
var boolean2 bool = true

变量的值是可以修改的。重新赋值时,需要遵守下面的语法规范。

variableName = newvalue

integer1 = -15
integer2 = 25
integer3 = 965
float1 = -52.99
string1 = "Hello There :)"
boolean1 = true
boolean2 = false

变量名称的约定

关于变量的命名,Go 建议用 单个 单词或者 小驼峰 的形式。用 下划线 不会产生语法错误,但是不推荐。

类型参考

尽管 Go 是静态类型语言,但是 Go 也为我们提供了声明变量的便捷方式。像下面这样声明变量时,可以省去变量类型

var variableName = initialValue

Go 会根据 initialValue 值的类型自动推导出变量类型。因此,这个语法只在声明一个新变量并赋值的时候生效。

var integer1 = 52 //int
var string1 = "Hello World" //string
var boolean1 = false //bool

简写符号

在声明变量时,Go 还提供了一个简写语法,可以同时省去  var 和 dataType

variableName := initialValue

当 Go 读到 := 符号时,它就知道新变量需要被赋予一个整形值。

integer1 := 52 //int
string1 := "Hello World" //string
boolean1 := false //bool

同时声明多个变量

还可以像下面这样,在一条语句中,同时声明多个同类型的变量

var var1, var2, var3 int

还可以在声明变量的同时赋值

var var1, var2, var3 int = 1, 2, 3

你也可以去掉数据类型,让 go 自动推导出变量的类型,像下面这样

var var1, var2, var3 = 1, 2.2, false

还可以用简写符号代替上面的写法

var1, var2, var3 := 1, 2.2, false

用一个 var 关键字同时声明多个类型的变量

var(
    var1 = 50
    var2 = 25.22
    var3 string = "Telefonía"
    var4 bool
)

关于简写符号

简写符号 := 只能用于函数体中。而且, := 符号左侧的变量中,必须至少有一个变量是第一次声明的变量。

通过这种简写语法,可以非常方便地实现在运行时给新变量赋值。比如像下面这样,把一个函数的返回值直接赋值给新变量。

package main

import (  
    "fmt"
    "math"
)

func main() {  
    a, b := 145.8, 543.8
    c := math.Min(a, b)
    fmt.Println("minimum value is ", c)
}

类型转换

Go 不支持不同类型变量之间的加减法等任何算数运算。要想进行算数运算,必须先转成同样的数据类型。Go 支持这种数据类型转换, 语法格式为 type(var).

var1 := 10 // int
var2 := 10.5 // float

// 非法的 
// var3 := var1 + var2

// 合法的
var3 := var1 + int(var2) // var3 == 20

当想要对不同类型的数据进行数学运算时,类型转换是非常重要的一步。Go 不允许在不同类型的变量之间做数学运算。

类型别名

只要按照下面的语法格式,就可以对任何系统自带的或用户自定义的类型声明别名

type aliasName aliasTo

在上面的语法格式中,aliasName 是你想要自定义的类型别名。 aliasTo 是定义新类型的参照类型。

例如,你想要自定义一个跟 float64 功能一样的 float 类型,就可以这样声明

type float float64

在上面的程序中,Go 会创建一个 float64 的副本,并命名为 float 类型。你可以像使用普通的 Go 类型一样,使用这个类型来声明变量。由于 Go 自身没有 float 类型名,而我又很讨厌每次都要写 float64,所以我通常都会这么自定义一下。

来看一下新定义的 float 类型的应用

package main

import "fmt"

type float float64

func main() {
    var f float = 52.2

    fmt.Printf("f has value %v and type %T", f, f)
}

在上面的代码中,我们把 float 定义为 float64 类型的别名,并创建了一个名为 f,类型为 float,初始值为 52.2 的变量。

输出

f has value 52.2 and type main.float

我们看到输出的类型是 main.float,因为 float 是一个自定义的类型,所以它必须附属于一个包。我们可以在程序的任何地方自定义类型,比如在方法里,或是在条件判断的代码块中。

如果自定义的类型别名的首字母是小写字母,那么这个类型就不能被其他包所引用。

而且,尽管上面定义的 floatfloat64 有着同样的属性,但是两个类型的值也是不能做比较运算的,因为它们是不同的类型。

package main

import "fmt"

type float float64

func main() {
    var f float = 52.2
    var g float64 = 52.2

    fmt.Println("f == g", f == g)
}

所以,上面的代码编译时会报错

invalid operation: f == g (mismatched types float and float64)

什么是常量

在 Go 中,常量就是有固定值的变量。任何试图改变常量值的行为都会引起运行出错。常量必须用 const 关键字声明并赋值。

const const_name [data_type] = fixed_value

data_type 是可选的,因为 go 会通过 fixed_value 的值自行推导数据类型。

在 Go 中,必须在开始编译之前给常量赋值。不能用函数的返回值给常量赋值。 const a = math.Sqrt(4) 是非法语句,因为 a 的值是要在运行中计算出来的。

同时声明多个常量

像变量一样,也可以在一个语句中,同时声明多个常量。

const const_1, const_2 = value_1, value_2

也可以像下面这样声明

const(
    const_1 = value_1
    const_2 = value_2
)

在带括号的const声明中,可以隐式重复表达式 - 这表示重复前面的表达式。

const(
    a = 1 // a == 1
    b = 2 // b == 2
    c     // c == 2
    d     // d == 2
)

iota

Go 的关键字 iota 可以用来声明枚举常量。这个关键字可以生成一系列自增值,从 0 开始,每次增加 1。

const(
    a = iota // a == 0
    b = iota // b == 1
    c = iota // c == 2
    d        // d == 3 ( 相当于 d = iota )
)

可以用  _ ( 空白标识符 ) 跳过值。 _ 会接收 iota + 1 的值,然后丢弃。

const (
    a = iota + 1 // a == 1
    _            // (implicitly _ = iota + 1 )
    b            // b == 3 (implicitly b = iota + 1 )
    c            // c == 4 (implicitly c = iota + 1 )
)

数字表达式

数值常量可以在表达式中自由地组合和匹配,只有赋值给变量或者用于需要类型的地方时,才需要考虑其数据类型。

计算的结果取决于参与运算的数字类型。例如,两个整数相除的结果仍然是一个整数。

var a = 11/2 // a == 5

当参与运算的两个数都是 int 时, 得到的结果就是整形。如果把其中一个数改成 float,那么得到的结果就是 float 类型的值。

var a = 11.0/2 // a == 5.5
var b = float32(11)/2 // a == 5.5
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.com/rungo/variables-and-c...

译文地址:https://learnku.com/go/t/27592

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 1

A 32-bit system will allocate 32 bits of memory and 64-bit system will allocate 64 bits of memory. Hence 32-bit system can store -2147483648 to 2147483647 and 64-bit system can store -9223372036854775808 to 9223372036854775807

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!