前言
  • 少做文字粘贴者,多做灵感总结
  • 嗯,看的文章很杂很乱,然后基本上都忘记写参考文章了,抱歉!
1.变量定义
  • 变量相当于内存中一个数据存储空间的表示

    数据存在存储空间中,则这个存储空间的名字叫变量(可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间(数据在房间里),同样,通过变量名可以访问到变量(值)。)

  • 变量表示内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型)

数学概念--->  没有固定值且可改变的数
计算机实现--> 一段或者多段用来储存数据的内存
  • go语言在编译的时候,会检查每个变量是否使用过,对于没有使用过的变量,会报编译错误
2.类型
  • 1.基本数据类型

整型       整数            int      
浮点型     小数            float   
字符型
布尔型     真假            bool
字符串     中英文字        string 
指针
数组                       
切片                       slice
集合                       map
通道/管道                  channel
结构体                     struct
函数                       func
          uint8别称        byte          强调数值是一个原始的数据而不是一个小的整数
          int32别名        rune          Unicode字符        
复数                       complex
接口
3.使用步骤
  • 声明变量(定义变量)
  • 非变量赋值
  • 使用变量
4.声明/赋值/初始化

这几个一般都不分家的,是在一块儿使用的,所以就放在一起了

1.一般形式/标准形式

// 三要素  变量=变量名+值+数据类型

//指定变量类型,声明后不赋值,使用默认值

		  //依赖于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.使用得很少,除非同时声明多个变量。

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.用处:在错误处理和函数返回值中大量使用组变量赋值
5.初始化默认值
  • 空接口可以代表任意类型,因为他就收任意类型

  • go中,数据类型都有一个默认值,当程序员没有赋值,编译器会使用默认值,默认值又叫零值。

  • 初始默认值就是 :初始但未引用

  • 1、基础类型

整形			均为 0
浮点			均为 0  // 有的说是0.0
复数			0+0i
布尔			false
字符串		    ""  // 空字符串

error		  nil
  • 2、复合类型

数组			默认值根据数组类型变化而变化	
		// 如 [3]int 为 [0,0,0]
结构体		   默认值根据随结构体内部类型变化而变化
        type Person struct {
            Name string
            Age  int
        }  		//默认值为{ 0} 即 Name为"" Age为0
	    var a *Person = &Person{}   a 就是上面的初始默认值
// 结构体指针跟这个是一样的
  • 3、引用类型

切片			nil  // 有争议,我运行出来是 空的切片
指针			nil	 // 结构体指针也是有点儿问题,是内部每个来说的
字典			nil
通道			nil
函数			nil
接口			nil
// 初始化但是未使用
var strList [3]string
fmt.Println(strList)  // [   ]
6.类型转换
// 将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 //编译不通过?为啥
7.匿名变量
  • 编码过程中遇到的没有名字的变量、类型和方法。
  • 使用
// 匿名变量使用:只需要在变量声明的地方使用下划线“_”
	a,b := 100,200
	a,_ := 100,200
  • 优点:不占用内存空间,不分配内存,匿名变量和匿名变量之间也不会因为多次声明而无法使用
8.变量作用域

1.作用域

// 变量在同一个作用域(在一个函数或者在代码块)内不能重名
一个变量(常量、类型和函数)在程序中有一定的作用范围
var i int = 20 
i := 10 
//注意上面是完整的,声明赋值

2.分类

1.局部变量

函数内声明的变量。作用域在函数体内,

最重要的是形式参数

2.全局变量

函数外声明的变量。
只需要在源文件中定义,就可以在所有源文件中使用。不包含这个全局变量的源文件需要用import引入全局变量说正在文件夹之后才能使用这个全局变量
 注意:1.全局变量的声明必须用var关键字开头
 	  2.在外部包使用全局的全局变量的首字母必须大写
 	  3.全局变量和局部变量的名称可以相同,但是函数体内的局部变量会优先考虑
	  4.在go函数外部定义变量就是全局变量

3.同一区域内变量

  • 该区域年内的数据值可以在同一类型内不断变化(重点)
func main(){
    var i int
    i = 30  //可以
    i = 10  //可以
    i = 50  //以上连写可以
    i = 1.2  //不可以,因为i的数据 类型只能是int
}
9.变量的生命周转期
  • 变量的作用周期和作用域有关系
  1. 全局变量:生命周期和整个程序的运行周期是一致的
  2. 局部变量:声明周期是动态的,从创建这个变量的声明语句开始,到这个变量不再被引用为止
  3. 全局变量和局部变量同名的情况下,局部变量生效。
  4. 形式参数和函数返回值:属于局部变量,函数被调用时创建,函数调用结束后被销毁
  5. 逃逸分析
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(垃圾回收机制)回收这个变量的内存空间。

10.起别名

1.类型起别名、类型声明

	// 别名:使用name和string相同。二者仍当做同一种类型运算。
    // 别名只在源码中存在,编译完成后,不会有别名类型。
type name = string // 类型别名(别名)
var myName name    // 变量声明使用 (%T,myName) ——>  string
=================================================================================
	// 声明:将name定义为一个新的类型,该类型拥有和string一样的特性
type name string   // 类型定义(声明)
var myName name    // 变量声明使用  (%T,myName)  ——>  main.name	
但是两者是不用的类型,不可用+进行拼接等运算。

2.函数类型别名

// 1.函数是一种数据类型,所以也可以自定义数据类型使用
type  myFunType  func( int ,int ) int

// 2.支持对函数返回值命名

func getSum(int)(sum int , sum int)
	sub = n1 + n2
	sum = n1 - n2
    return

3.非本地类型不能定义方法

  • 能够给各种类型起名字,但是不意味着可以在自己的包里为这些类型添加方法,

  • 就是在其他包中定义过了,不能在自己的包里重复定义

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 包中。
	
跳转