变量相当于内存中一个数据存储空间的表示
数据存在存储空间中,则这个存储空间的名字叫变量(可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间(数据在房间里),同样,通过变量名可以访问到变量(值)。)
变量表示内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型)
数学概念---> 没有固定值且可改变的数
计算机实现--> 一段或者多段用来储存数据的内存
整型 整数 int
浮点型 小数 float
字符型
布尔型 真假 bool
字符串 中英文字 string
基本数据类型,变量存的就是值
指针
数组
切片 slice
集合 map
通道/管道 channel
结构体 struct
函数 func
uint8别称 byte 强调数值是一个原始的数据而不是一个小的整数
int32别名 rune Unicode字符
复数 complex
接口
这几个一般都不分家的,是在一块儿使用的,所以就放在一起了
// 三要素 变量=变量名+值+数据类型
//指定变量类型,声明后不赋值,使用默认值
//依赖于type的内部初始化机制,被初始化为默认值
标准声明: var name type
name = 表达式 //后续赋值
--------------------------------------------------------
初始化:
//表达式可以是:数
name := 表达式 // 简短格式/短变量,用于函数内部
var name type = 表达式 //显式地标明变量的类型,在多变量同时声明时可以用到
var name = 表达式 //类型推导。编译器会自动推导name变量的类型,使用得很少,除非同时声明 多个变量。
解读:var 声明变量的关键字
name 变量名(变量的名字)
type 变量的类型
表达式 字,字符串,不等式......
标准格式
1.顺序不能变换,
2…用于需要显式指定变量的地方,或变量稍后会被重新赋值而与初始值无关紧要的地方
简短格式/短变量:
1.只能用在函数内部,用于局部变量的声明和初始化,main()函数也算
package级别不要用2.冒号( := )左边的变量必须是没有定义过的变量,若定义过就会编译错误
3.定义变量,同时显示初始化,不能提供数据类型
4.短变量声明多用于开发中
5.多个短变量声明和赋值中,至少要一个新的变量出现在左值中,即便有其他变量可能是重复定义的。编译也不会出错
conn, err := net.Dial(“tcp”, “127.0.0.1:8080”)
conn2, err := net.Dial(“tcp”, “127.0.0.1:8080”)
上方在一块儿的代码,不会出现err报错
类型推导
1.go语言为了提高精度,对于浮点型数据会推到位float64类型
2.使用得很少,除非同时声明多个变量。
//不同类型
var (a int
...
b bool)
------------------
var (a = 300
b = 100 )
//相同类型
var a,b int
i,j = 1,"wang" //组变量赋值,变量的左值和右值,按照从左到右的顺序赋值,
-------------------------------
var a,b int = 100, "name"
a,b := 100, "name" //组变量赋值
1.用处:在错误处理和函数返回值中大量使用组变量赋值
空接口可以代表任意类型,因为他就收任意类型
go中,数据类型都有一个默认值,当程序员没有赋值,编译器会使用默认值,默认值又叫零值。
初始默认值就是 :初始但未引用
整形 均为 0
浮点 均为 0 // 有的说是0.0
复数 0+0i
布尔 false
字符串 "" // 空字符串
error nil
数组 默认值根据数组类型变化而变化
// 如 [3]int 为 [0,0,0]
结构体 默认值根据随结构体内部类型变化而变化
type Person struct {
Name string
Age int
} //默认值为{ 0} 即 Name为"" Age为0
var a *Person = &Person{
} a 就是上面的初始默认值
// 结构体指针跟这个是一样的
切片 nil // 有争议,我运行出来是 空的切片
指针 nil // 结构体指针也是有点儿问题,是内部每个来说的
字典 nil
通道 nil
函数 nil
接口 nil
切片
// 初始化但是未使用
var strList [3]string
fmt.Println(strList) // [ ]
// 将a转化为b类型的值
类型b的值 = b的类型 (类型A的值)
//注意
1.类型转换可以从大范围到小范围,也可以从小范围到大范围
2.被转化的是变量储存的数据(即值)。变量本身的数据类型没有变化
var i int32 = 100
var n3 int64 = int64(i) //i 的数据类型没有发生变化,知识它存的值转化为int64,并给了n3
3.大范围转小范围可能导致数据溢出
var n1 int32 = 12
var n3 int8
var n4 int8
n3 = int8(n1)+127 // 编译通过,但是结果不是127+12,按照溢出处理
n4 = int8(n1)+128 //编译不通过?为啥
// 匿名变量使用:只需要在变量声明的地方使用下划线“_”
a,b := 100,200
a,_ := 100,200
// 变量在同一个作用域(在一个函数或者在代码块)内不能重名
一个变量(常量、类型和函数)在程序中有一定的作用范围
var i int = 20
i := 10
//注意上面是完整的,声明赋值
函数内声明的变量。作用域在函数体内,
最重要的是形式参数
函数外声明的变量。
只需要在源文件中定义,就可以在所有源文件中使用。不包含这个全局变量的源文件需要用import引入全局变量说正在文件夹之后才能使用这个全局变量
注意:1.全局变量的声明必须用var关键字开头
2.在外部包使用全局的全局变量的首字母必须大写
3.全局变量和局部变量的名称可以相同,但是函数体内的局部变量会优先考虑
4.在go函数外部定义变量就是全局变量
func main(){
var i int
i = 30 //可以
i = 10 //可以
i = 50 //以上连写可以
i = 1.2 //不可以,因为i的数据 类型只能是int
}
var global *int
func f() {
var x int
x = 1
global = &x
}
//函数 f 里的变量 x 必须在堆上分配,因为它在函数退出后依然可以通过包一级的 global 变量找到,虽然它是在函数内部定义的。用Go语言的术语说,这个局部变量 x 从函数 f 中逃逸了。
func g() {
y := new(int)
*y = 1
}
//函数 g 返回时,变量 *y 不再被使用,也就是说可以马上被回收的。因此,*y 并没有从函数 g 中逃逸,编译器可以选择在栈上分配 *y 的存储空间,也可以选择在堆上分配,然后由Go语言的 GC(垃圾回收机制)回收这个变量的内存空间。
// 别名:使用name和string相同。二者仍当做同一种类型运算。
// 别名只在源码中存在,编译完成后,不会有别名类型。
type name = string // 类型别名(别名)
var myName name // 变量声明使用 (%T,myName) ——> string
=================================================================================
// 声明:将name定义为一个新的类型,该类型拥有和string一样的特性
type name string // 类型定义(声明)
var myName name // 变量声明使用 (%T,myName) ——> main.name
但是两者是不用的类型,不可用+进行拼接等运算。
// 1.函数是一种数据类型,所以也可以自定义数据类型使用
type myFunType func( int ,int ) int
// 2.支持对函数返回值命名
func getSum(int)(sum int , sum int)
sub = n1 + n2
sum = n1 - n2
return
能够给各种类型起名字,但是不意味着可以在自己的包里为这些类型添加方法,
就是在其他包中定义过了,不能在自己的包里重复定义
package main
import ("time")
// 定义time.Duration的别名为MyDuration,起别名
type MyDuration = time.Duration
// 为MyDuration添加一个函数,为这个别名添加一个方法。
func (m MyDuration) EasySet(a string) {
}
func main() {
}
* 编译出现错误
cannot define new methods on non-local type time.Duration
* 分析
编译器提示:不能在一个非本地的类型 time.Duration 上定义新方法,
// 非本地类型指的就是 time.Duration 不是在 main 包中定义的,而是在 time 包中定义的,与 main 包不在同一个包中,因此不能为不在一个包中的类型定义方法。
!!!
// 就是在其他包中定义过了,不能重复定义
* 更正
1.将 type MyDuration = time.Duration 修改为 type MyDuration time.Duration,也就是将 MyDuration 从别名改为类型;
2.将 MyDuration 的别名定义放在 time 包中。