变量
GO变量总是有固定的数值类型,类型决定了变量内存的长度和存储格式。我们只能修改变量,无法改变类型
编译后的机器码从不使用变量名,而是直接通过内存地址访问目标数据
定义
关键字 var 用于定义变量
var x int //自动初始化为0 var y = false //自动推断为bool类型 var x,y int
多变量赋值
var x,s = 100,"abc" var x,y = y+3,x+2
首先计算出所有右值,然后赋值
建议以组的方式定义变量
var( x , y int a , b = 100 ,'abc' )
简短模式
x := 100 a,b := 1,'abc'
简短模式限制:
定义变量,同时显示初始化
不能提供数据类型
只能用在函数内部
例:
package main var x = 100 //全局变量 func main(){ println(&x,x) x:="abc" //重新定义和初始化同名局部变量 println(&x,x) } 输出 0x49a018 100 //对比内存地址 0xc420039f68 abc
简短模式也可以退化赋值(变量内存地址不发生改变)
条件:最少有一个新变量被定义,且必须是同一作用域
编译器将未使用局部变量当作错误
命名
以字母或下划线开始,由多个字母,数字,下划线组成
空标识符
“_” 通常作为忽略占位符使用,无法读取其内容
常量 const
const x,y int = 123,0x22 const c = '哦'
常量定义 右值不能超出常量类型取值范围,否则会溢出
常量可以是某些编译器能计算出结果的表达式
常量组不知定类型和初始值,则与上一行非空常量右值相同
例
const( x uint16 = 120 y s = "abc" z )
枚举
借助iota 标识符实现一组自增常量
const( x = iota //0 y //1 z //2 ) const( _,_ = iota,iota * 10 //0, 0*10 a,b //1, 1*10 c,d //2, 2*10 )
中断iotaz自增
const( a = iota //0 b //1 c = 100 //100 d //100 e = iota //4 恢复iota自增 f //5 )
自增默认数据类型 int 可显示指定类型
建议用自定义类型实现用途明确的枚举类型。但不能将取值范围限定在预定义的枚举内
数字常量不会分配存储空间。
基本类型
长度
bool byte uint8 int,uint 32或64 依据平台 int8,uint8 -128~127,0~255 int16,uint16 -32768~32767,0~65535 int32,uint32 -21亿~21亿,0~42亿 int64,uint64 float32 float64 complex64 complex128 rune Unicode Code Point,int32 uintptr 足以存储指针的uint string array 数组 struct 结构体 function 函数 interface 接口 map 字典 slice 切片 channel 通道
标准库math 定义了各种数字类型的取值范围
标准库strconv 可在不同进制(字符串)间转换
例:
package main import "strconv" func main(){ a,_:=strconv.ParseInt("1100100",2,32) println (a) println("0b" + strconv.FormatInt(a,2)) } 输出 100 0b1100100
别名:
byte alias for uint8 rune alias for int32
引用类型:特指 slice,map,channel
内置函数 new按指定类型长度分配零值内存,返回指针,并不关心类型内部构造和初始化方式
new 为引用分配内存,但创建不完整。
引用类型必须使用make函数创建
例:
package main func mkslice() []int{ s := make([]int,0,10) s = append(s,100) return s } func mkmap() map[string]int { m := make(map[string]int) m["a"] = 1 return m } func main(){ m := mkmap() println(m["a"]) s := mkslice() println(s[0]) } 输出: 1 100
类型转换
除常量,别名类型以及未命名类型
GO强制要求使用显式类型转换
混合类型表达式必须确保类型一致
不能将非bool类型结果当作 true/false
如果转换目标是指针,单向通道或没有返回值的函数类型,那么必须使用括号
用括号,让编译器将*int解析为指针类型
(*int)(p) *(int(p)) (<-chan int)(c) <-(chan int(c)) (func())(x) func() x
自定义类型
使用type定义用户自定义类型
type flags byte
多个type定义可以合并成组
type( user struct{ name string age uint8 } event func(string) bool )
自定义类型只表明有相同的底层数据结构,属完全不同的两种类型
不会继承基础类型的其他信息(包括方法)不能视作别名,不能隐式转换,不能直接用于比较表达式
例:
type data int var d data = 10 var x int = d //错误
未命名类型
数组,切片,字典,通道灯类型与具体元素类型或长度等属性有关,故称作未未命名类型。也可以用type为其提供具体的名称,将其变为命名类型
具有相同声明的未命名类型称为同一类型
具有相同基类型的 指针
具有相同元素类型和长度的 数组(array)
具有相同元素类型 切片(slice)
具有相同键值类型 字典(map)
具有相同数据类型及操作方向 通道(channel)
具有形同字段序列(字段名,字段类型,标签,以及字段顺序)结构体(struct)
具有相同签名(参数和返回值列表,不包括参数名) 函数(func)
具有相同方法集(方法名,方法签名,不包括顺序) 接口(interface)
例:
var a struct{ x int 'x' } var b struct{ x int } b=a //错误
var a func(int,string) var b func(string,int) a=b //错误 参数顺序也属于签名
未命名类型转换规则
所属类型相同
基础类型相同,且其中一个是未命名类型
数据类型相同,将双向通道赋值給单向通道,且其中一个为未命名类型
将默认值 nil 赋值給切片,字典,通道,指针,函数或接口
对象实现了接口
例:
type data [2]int var d data = [2]int{1,2} //基础类型相同,右为未命名类型
a:=make(chan int,2) var b chan <- int = a //双向通道转换为单向通道,b为未命名类型
原文地址:http://blog.51cto.com/13558754/2102848