前言
很多开发语言中都存在变量,而go
也是。需要注意go
是静态类型语言,所以不能像某些语言(例如JavaScript
)那样在运行期间改变变量的类型。下面会给大家介绍变量如何使用与使用期间可能存在的坑。注意本文是基于go 1.12.5
的,可能会与其他版本存在差异。
变量命名规则
既然有变量就必然有变量名,而在很多支持变量的语言中,变量名一般都会有命名规则。而go
也不例外,下面是go
的变量名命名规则:
- 变量名由字母、数字、下划线组成,其中首个字符不能为数字。
- 变量名不能与
go
语言中的保留字相同
PS:建议命名变量名按照驼峰命名法
下面会简单介绍一下保留字的概念以及go
中保留字
保留字
保留字指的是在高级语言中已经定义过的字,使用者不能再将这些字作为变量名或过程名使用。所以如果出现重名,就无法区分这个是保留字还是变量名了。而在go
中保留字并不多,才25个:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
变量名示例
下面我会列出一些变量名的示例给大家参考,首先是合法变量名:
day
day1
day_1
last_name
lastName
然后是演示一些不合法的变量名:
1day //以数字开头
day-1 // 使用了非法字符-
var // 保留字
变量声明
在go
语言中,变量的声明有好几种方法,下面会给大家一一列举。
使用var声明变量
在go
中有一个用于声明变量的关键字var
,下面会演示如何使用var
声明变量
var i int = 10 //语法为 var 变量名 变量类型 = 变量值
但是其实使用var
时可以不需要赋值,由go
根据设定的类型自动赋默认值。例如下面的示例
var i int // 语法为 var 变量名 变量类型,此时这个变量的默认值为0
而有些时候根本就没有必要在变量声明中指定变量类型,因为可以根据变量值进行类型推导,而go
也恰好支持。
var i =10 //利用类型推导,不需要指定变量的类型
使用:=声明变量
除了使用var
声明变量外,在函数中也可以使用:=
来对变量赋值,但是也只可以用于函数中。
func main(){
i := 123
fmt.Println("i=",i)
}
声明多个变量
有时候我们会需要声明多个变量,而go
也支持同时一次声明多个变量
var i,j,k int // i,j,k的类型都是int
上面的例子是声明多个类型相同的变量,但是其实go
也支持声明多个不同类型的变量,下面的写法叫做变量组
var (
i int
j float32
k float64
)
当然了同时声明多个变量也是支持类型推导的
var i,j,k = 1,"test",1.2 //按照声明的顺序依次赋值,等价于var i = 1 var j= "test" var k = 1.2
多个变量声明时,如果变量的赋值需要计算,会先进行计算后,再依次进行赋值(需要注意计算时不能涉及声明中的变量)
var i,j = 100+1,100-1 //执行顺序:(100+1=101)=>(100-1=99)=>(var i=101)=>(var j=99)
变量使用
声明了变量之后,当然是开始使用了。而变量在使用时也会遇到各式各样的坑
基本使用
下面会使用一个从1
累加到100
的例子演示如何使用变量(这个示例使用了for
循环关键字,但是不会影响大家理解)
package main
import "fmt"
func main() {
var total = 0 // 累加值
for i := 1; i <= 100; i++ {
total = total + i // 累加计算
}
fmt.Print(total) // 输出累加值
}
输出结果
5050
变量分类
在go
中,变量分为2
种:
- 全局变量:必须使用
var
声明,可以声明后不使用 - 局部变量:可以使用
var
或者:=
声明,声明后必须被使用。否则编译失败
例如以下的例子
package main
import "fmt"
var global = 100 //声明了全局变量,但是不使用
func main() {
var local = 200 //声明局部变量,必须要使用,否则编译失败
fmt.Print(local)
}
变量作用域
go
的变量存在作用域,存在以下两条规则
- 全局变量和局部变量如果同名,在局部变量的作用域内(一般为函数内),使用变量名访问的是局部变量
- 局部变量也存在作用域,下面使用一个例子来演示
输出结果package main import "fmt" func main() {// main作用域 var local = 0 // 累加值 if true {// if作用域 var local = "hello" // 声明了一个同名的变量 fmt.Println(local) //此时访问的是if作用域内的local } fmt.Println(local) // main作用域的local不受影响 }
100 0
指针与引用
go
语言是支持指针与引用,这个特性如果是学过C/C++
的朋友应该会了解,下面使用一个示例演示
package main
import "fmt"
func main() {
i := 1
j := &i // i的指针
fmt.Println("i=",i)
fmt.Println("j=",j) // 输出指针,即内存地址
fmt.Println("*j=",*j) // 通过指针引用i
}
输出结果
i= 1
j= 0xc000094000
*j= 1
使用_处理未使用的局部变量
当我们在使用时,会出现一些局部变量不需要使用,但是我们又不得不声明,例如下面的例子
package main
import "fmt"
func main() {
m := map[int]int{
1: 1,
2: 2,
3: 3,
} // 声明了一个map
for _,v := range m{ // 遍历map,由于不需要输出key,使用_占位
fmt.Println(v) // 需要注意go中的map每次遍历的顺序都是随机的,所以输出结果也是随机的
}
}
输出结果
3
1
2