变量
变量的声明
var 变量名字 类型 = 表达式
其中“类型”或“= 表达式”两个部分可以省略其中的一个,如果省略的是类型,那么可以根据初始化表达式推导。如果省略的是“= 表达式”那么用零初始化变量。
Go语言中不存在未初始化的变量
类型 | value |
---|---|
数值 | 0 |
布尔 | false |
字符串 | 空字符串 |
接口或引用类型(slice、指针、map、chan和函数) | nil |
数组或结构体(聚合类型) | 每个元素或字段都是对应该类型的零值 |
同时声明一组变量
var i, j, k int // int, int, int
var b, f, s = true, 2.3, "four" // bool, float64, string
一组变量也可以通过调用一个函数,由函数返回的多个返回值初始化:
go语言的函数是可以返回多个值的
var f, err = os.Open(name) // os.Open 返回一个文件和一个错误
简短变量声明
以“名字 := 表达式”形式声明变量,变量的类型根据表达式来自动推导
i:=1
j:=0.0
简短声明也可以同时声明一组变量
name,sex,age:="张三",20,"男"
也可以用做函数的返回值
f, err := os.Open(name)
比较微妙的地方
简短变量声明左边的变量可能并不是全部都是刚刚声明的。如果有一些已经在相同的词法域声明过了,那么简短变量声明语句对这些已经声明过的变量就只有赋值行为了。而且简短变量声明语句中至少要有一个新的变量
name,score:="张三",100
name,myscore:="my",100//这样没问题
name,socre:="李四",99//error:no new variables on left side of:=
指针
用var x int 声明一个变量,那么&x产生一个指向变量x的指针,类型是*int
和C语言差不多
var x int
x=1
var p *int
p=x
fmt.Println(*p)//1
*p=2
fmt.Println(x)//2
注意
在go语言中返回函数中临时变量的地址是安全的。
go语言的编译器会自动选择在栈上还是在堆上分配局部变量的存储空间
列如
var global *int
func f(){
var x int
x=1
global=&x
}
这里的变量x是分配在堆上的,因为在函数退出后仍然要通过包一级的变量global找到
func g(){
y:=new(int)
*y=1
}
这里的变量y是分配在栈上的,虽然用的是new方法,但是这是go语言
new函数
表达式new(type)可以创建一个type类型的匿名变量,并初始化为0值,然后返回变量地址
p:=new(int)//变量p类型为*int
new只是一个预定义的函数,不是关键字,所以可以把new重定义为别的类型变量
func f(old ,new int) int{
return new-old
}
赋值
元组赋值
元组赋值是一种特殊形式的赋值语句,可以同时更新多个变量。在赋值前,赋值语句右边的表达式会先进行求值,然后统一赋值给左边的变量。
x,y=y,x//交换两个变量
示例
求斐波那契数列的第N个数
func fib(n int) int{
x,y:=0,1
for i:=1;i<n;i++{
x,y=y,x+y
}
return x
}
表识符"_"
有些函数会返回多个值,那么当这样的函数出现在元组赋值的右边的时候,在左边就要有对应个数的变量
f,err=os.Open("file.txt")
f,_=os.Open("file.txt")
使用_来丢弃一个不需要的值
类型定义
这里给类型起别名类似c语言,只是语法稍稍不同
type 类型名字 底层类型
package main
import "fmt"
func main() {
type bigint int64 //给int64起一个别名为bigint
var a bigint
fmt.Printf("a1的类型为%T\n", a) //输出main.bigint
type (
char byte
long int
)
var (
ch char = 'a'
a1 long = 123123
)
fmt.Println("ch = ", ch, " a1 = ", a1)
}