# 变量

这是我们[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是强类型编程语言，因此给变量赋值时只能赋予类型匹配的值，否则会报错。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sunwenfei.gitbook.io/sunwenfei/golang/golang-ji-chu-jiao-cheng/bian-liang-leixing-chang-liang/bian-liang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
