# 变量

这是我们[Golang基础教程](https://sunwenfei.gitbook.io/sunwenfei/golang/golang-ji-chu-jiao-cheng)的第三节，介绍Golang中的变量相关内容。

#### 什么是变量

变量用来存储某种类型的值，Golang中有若干种不同的声明变量的语句。

#### 声明单个变量

`var name type`用来声明单个变量。

```go
package main

import "fmt"

func main() {
    var age int // 变量声明
    fmt.Printf("my age is %d\n", age)
}
```

[点击这里](https://play.golang.org/p/aBeqYELxT3p)使用Go Playground在线运行。

前面的语句`var age int`声明了一个`int`类型的变量`age`，但是并没有给该变量赋值。在Golang中，如果一个变量声明时未手动赋值，Golang会自动将该变量初始化为对应类型的**零值**（注意每种类型都有其独特的零值，比如`int`类型的零值为0）。这里由于`age`声明为了`int`类型，因此Golang自动将该变量初始化为0。运行该程序会输出如下结果：

```
my age is 0
```

我们可以给某种类型的变量赋予该类型的任何值，比如这里的`age`变量，我们可以赋予任何大小的整数值：

```go
package main

import "fmt"

func main() {
    var age int // 变量声明
    fmt.Printf("my age is %d\n", age)
    age = 29 // 给age变量赋值
    fmt.Printf("my age is %d\n", age)
    age = 54 // 给age变量赋另一个值
    fmt.Printf("my age is %d\n", age)
}
```

[点击这里](https://play.golang.org/p/eVS8mFhbA69)使用Go Playground在线运行。

该程序输出如下：

```
my age is 0
my age is 29
my age is 54
```

#### 变量声明的同时赋初值

变量声明的同时可以赋初值，语法如下：`var name type = initialvalue`。

```go
package main

import "fmt"

func main() {
    var age int = 29 // 变量声明并赋初值
    fmt.Printf("my age is %d\n", age)
}
```

[点击这里](https://play.golang.org/p/ck4IWnktyKP)使用Go Playground在线运行。

这段程序中变量`age`被声明为`int`类型，同时被赋予了初值`29`，输出如下：

```
my age is 29
```

#### 类型推断

如果一个变量声明的同时并进行了赋值，那么Golang可以自动根据赋予的初值来推断出变量的类型，因此这种情况下声明变量时可以将声明语句`var type name = initalvalue`中的`type`字段省掉，变为如下形式：`var name = initialvalue`。

下面的程序中`age`变量声明时赋予了初值`29`，因此Golang可以自动推断出`age`变量的类型为`int`。

```go
package main

import "fmt"

func main() {
    var age = 29 // 根据初始值自动推断age类型
    fmt.Printf("my age is %d\n", age)
}
```

[点击这里](https://play.golang.org/p/28zyHuR7BHz)使用Go Playground在线运行。

#### 同时声明相同类型的多个变量

在Golang中，单个语句可以同时声明某种相同类型的多个变量，语法如下：`var name1, name2 type = initialvalue1, initialvalue2`。

```go
package main

import "fmt"

func main() {
    var width, height int = 100, 50 // 同时声明两个变量
    fmt.Println("width is ", width, "height is ", height)
}
```

[点击这里](https://play.golang.org/p/QsvUWeHKeRR)使用Go Playground在线运行。

这段程序中由于`name1`和`name2`两个变量声明时并赋予了初值，因此Golang可以推断出变量类型，因此可以省去`type`字段：`var width, height = 100, 50`。

如果这两个变量声明时不赋初值，那么就不能省去`type`字段，这时Golang会自动初始化为`零值`。

```go
package main

import "fmt"

func main() {  
    var width, height int
    fmt.Println("width is", width, "height is", height)
    width = 100
    height = 50
    fmt.Println("new width is", width, "new height is ", height)
}
```

[点击这里](https://play.golang.org/p/QPooK5ZJpXz)使用Go Playground在线运行。

该程序输出如下：

```
width is 0 height is 0
new width is 100 new height is  50
```

#### 同时声明不同类型的多个变量

当然了，Golang也可以同时声明不同类型的多个变量，语法如下：

```go
var (
    name1 = initialvalue1
    name2 = inititalvalue2
    name3 type3
)
```

举个例子：

```go
package main

import "fmt"

func main() {
    var (
        name = "naveen"
        age = 29
        height int
    )
    fmt.Println("my name is", name, ", age is", age, "and height is", height)
}
```

[Go Playground在线运行](https://play.golang.org/p/YbTsPv2PpOj)

这里同时声明了3个变量，`string`类型的`name`，`int`类型的`age`和`height`，该程序输出如下：

```
my name is naveen , age is 29 and height is 0
```

如果我们想要声明的不同类型的多个变量均提供手动初始值，那么也可以采用下面的形式：

```go
package main

import "fmt"

func main() {
    var name, age = "naveen", 29
    fmt.Println("my name is", name, ", age is", age)
}
```

[Go Playground在线运行](https://play.golang.org/p/37_uoKOfPKn)

#### 变量声明简写形式

Golang提供了一种非常简洁的声明变量的缩写形式，语法如下：`name := value`，注意这种方法要求手动赋予变量初值。

```go
package main

import "fmt"

func main() {  
    name, age := "naveen", 29 // 变量声明简写

    fmt.Println("my name is", name, "age is", age)
}
```

[Go Playground在线运行](https://play.golang.org/p/RiTVFSfLx29)

执行结果如下：

```
my name is naveen age is 29
```

切记，变量声明简写形式要求所有声明的变量都在`:=`右侧手动赋予初值。下面的程序运行会报错：

```
assignment mismatch: 2 variable but 1 values
```

就是因为变量`age`未在`:=`右侧手动赋予初值：

```go
package main

import "fmt"

func main() {  
    name, age := "naveen" //error

    fmt.Println("my name is", name, "age is", age)
}
```

[Go Playground在线运行](https://play.golang.org/p/v1Yz9PgShmj)

#### 仅新声明的变量支持简写声明赋值

仅当`:=`左侧声明的变量至少一个是**新**声明变量时才可使用简写形式。

```go
package main

import "fmt"

func main() {  
    a, b := 20, 30 // declare variables a and b
    fmt.Println("a is", a, "b is", b)
    b, c := 40, 50 // b is already declared but c is new
    fmt.Println("b is", b, "c is", c)
    b, c = 80, 90 // assign new values to already declared variables b and c
    fmt.Println("changed b is", b, "c is", c)
}
```

[Go Playground在线运行](https://play.golang.org/p/sSm_pUxrk-V)

这段程序中语句`b, c := 40, 50`之所以合法是因为虽然变量`b`前面已声明过，但是变量`c`是新声明的变量，执行结果如下：

```
a is 20 b is 30
b is 40 c is 50
changed b is 80 c is 90
```

但是如果是下面的程序，则执行时会报错：

```
no new variables on left side of :=
```

是因为变量`a`，`b`前面均已声明过。

```go
package main

import "fmt"

func main() {  
    a, b := 20, 30 //a and b declared
    fmt.Println("a is", a, "b is", b)
    a, b := 40, 50 //error, no new variables
}
```

[Go Playground在线运行](https://play.golang.org/p/5-zwbqnHWRy)

Golang中变量赋值不仅可以赋予字面量值，还可以赋予运行时计算结果值。

```go
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 Playground在线运行](https://play.golang.org/p/SeGcL6BlvZ7)&#x20;

这段程序中变量`c`被赋予的值即为程序运行时计算结果值。注意，由于Golang是强类型编程语言，因此给变量赋值时只能赋予类型匹配的值，否则会报错。
