变量
1 变量是什么
变量指定了某存储单元(Memory Location)的名称,该存储单元会存储特定类型的值。在 Go 中,有多种语法用于声明变量。
2 声明变量的基本方式
2.1 第一种方式:全定义var name type = initialvalue
package main
import "fmt"
func main() {
// var关键字 变量名 变量类型 = 变量值
var age int =10 //在go中,变量定义了就必须使用,如果不使用就报错。模块导入了不使用也报错。
fmt.Println(age)
}
2.2 第二种方式:类型推导(类型不需要写了) var name = initialvalue
如果变量有初始值,那么 Go 能够自动推断具有初始值的变量的类型。因此,如果变量有初始值,就可以在变量声明中省略 type
。
package main
import "fmt"
func main() {
var age = 10
var name ="zell"
fmt.Println(age) //打印并换行
fmt.Print(name) //打印不换行
fmt.Printf("%T\n",age) //查看变量类型,\n换行
fmt.Printf("%T",name) //查看变量类型,不换行
fmt.Printf("%p",&name) //查看内存地址
}
2.3 第三种方式:简略声明name := initialvalue
类型 typy
和var
关键字都不写(必须表明是在定义变量,定义变量和使用变量是两个阶段,python中合二为一了),冒号和等号是一体
package main
import "fmt"
func main() {
a := 10
var a int = 100 //重复定义,报错
var a = 99 //重复定义,报错
a := 99 //重复定义,报错
a = 99 //使用变量(赋值变量),是允许的
b = 99 //没有定义b变量,直接使用,报错
fmt.Println(a)
}
简短声明的语法要求 := 操作符的左边至少有一个变量是尚未声明的。考虑下面的程序:
package main
import "fmt"
func main() {
a, b := 20, 30 // 声明变量a和b
fmt.Println("a is", a, "b is", b)
b, c := 40, 50 // b已经声明,但c尚未声明,我们觉得是重复定义,但goland不认为重复,因为冒号左侧,只要有一个没有定义过的变量,goland就不认为重复
fmt.Println("b is", b, "c is", c)
b, c = 80, 90 // 给已经声明的变量b和c赋新值
fmt.Println("changed b is", b, "c is", c)
}
但是如果我们运行下面的程序:会抛出 no new variables on left side of :=
的错误,这是因为 a 和 b 的变量已经声明过了,:= 的左边并没有尚未声明的变量。
package main
import "fmt"
func main() {
a, b := 20, 30 // 声明a和b
fmt.Println("a is", a, "b is", b)
a, b := 40, 50 // 错误,没有尚未声明的变量,重复定义
}
变量也可以在运行时进行赋值。考虑下面的程序:c 的值是运行过程中计算得到的,即 a 和 b 的最小值。
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 是强类型(Strongly Typed)语言,因此不允许某一类型的变量赋值为其他类型的值。下面的程序会抛出错误 cannot use "naveen" (type string) as type int in assignment
,这是因为 age 本来声明为 int 类型,而我们却尝试给它赋字符串类型的值。
package main
func main() {
age := 29 // age是int类型
age = "naveen" // 错误,尝试赋值一个字符串给int类型变量
}
3 其他变形方式
3.1 只定义不赋值 var name type
package main
import "fmt"
func main() {
var age int // 变量声明
fmt.Println("my age is", age)
}
语句 var age int
声明了一个 int 类型的变量,名字为 age。我们还没有给该变量赋值。如果变量未被赋值,Go 会自动地将其初始化,赋值该变量类型的零值(Zero Value)。本例中 age 就被赋值为 0。如果你运行该程序,你会看到如下输出:
my age is 0
变量可以赋值为本类型的任何值。上一程序中的 age 可以赋值为任何整型值(Integer Value)。
如果是只定义,不赋值,只能用全定义方式var name type
,类型推导方式var name
报错,因为它不知道变量的类型,变量的类型在定义阶段就要确定。
3.2 声明多个变量
Go 能够通过一条语句声明多个变量。
声明多个变量的语法是 var name1, name2 type = initialvalue1, initialvalue2
package main
import "fmt"
func main() {
var width, height int = 100, 50 // 声明多个变量, 声明了type,初始化值只能为int类型
var width, height = 100, "zell" // 声明多个变量,类型推导方式,没有声明type,初始化值可以任意类型
width, height :=100, "zell" // 声明多个变量,简略方式,没有声明type,初始化值可以任意类型
fmt.Println("width is", width, "height is", heigh)
}
3.3 声明多个变量,在一个语句中声明不同类型的变量
package main
import "fmt"
func main() {
var (
name = "zell"
age = 29
height int
)
fmt.Println("my name is", name, ", age is", age, "and height is", height)
}
这里我们声明了 string 类型的 name、int 类型的 age 和 height(初值为0)
4 总结
1 变量类型在定义阶段就确定了,一旦确定,不允许改变,这是编译型语言的特性。
// python之所以可以改变变量类型,是因为python中一切皆对象,a=10, 在python中,其实是a指向一个内存地址,内存地址指向了10,内存地址占的比特位是固定大小,所以指向任意类型都可以。
// go语言中,就是a直接指向10,假设10属于int8类型,占8个比特位,换成字符串需要扩充比特位,是不能扩的,因此不能改变数据类型。
2 变量不可以重复定义。
3 变量要先定义再使用。
5 变量的作用域范围
补充:在同一个包下,函数名不能重名。在之前的.go文件的main包下,定义了test函数,因此这里用test1
package main
import "fmt"
var a int //定义全局变量a,全局有效,只要改了,就是改了
func main() {
fmt.Println(a) //0 初始值为0
a = 19 //赋值操作,全局修改
fmt.Println(a) //19
test1() //99 调用test1,函数内部赋值操作又全局修改
fmt.Println(a) //99
}
func test1() {
a = 99
fmt.Println(a)
}
package main
import "fmt"
var a int
func main() {
var a int
fmt.Println(a) //0
a = 19 //局部的变量a
fmt.Println(a) //19
test1() //99
fmt.Println(a) //19 局部优先,局部定义了变量a,先用局部的
}
func test1() {
a = 99 //全局的变量a
fmt.Println(a)
}