golang学习笔记(一)

我的go语言完全是自学,所以将市面上所有能买到的golang书籍都买来看了。

基础都已研究完毕今天开始做总结,并且开始阅读go高级编程和进行实战演练。

go程序 4个主要声明 vartypeconstfun

包级别实体不仅对声明的包中可见,对同一个包所有源文件均可见。

 

变量声明

var name type = expression

其中类型和表达式可以忽略其中一个,但是不能全都忽略,忽略表达式则变量name的值为对应类型的零值,忽略typename的类型根据表达式的类型来定。

 

类型零值

数字 0 , 布尔 false,字符串””,接口和引用类型 nil

类型0值保证了go语言不存在未初始化代码。

 

短变量声明

用来声明和初始化局部变量。依赖一个明确的作用域。

格式:name := expression

name的类型由expression来定。

短变量声明不需要声明所有左边的变量,如果一些变量已经在词法块中声明,那么对于这些变量,短变量声明等同于赋值。

例:

a:=1

a,b:=2,3

注意短变量声明的作用就是表示声明,其中一个变量必须是未声明的才行,如果两个变量都在词法块中声明过就会报错。

 

指针

指针的值是变量存放的地址。不是所有的值都有地址,但是所有的变量都有。使用指针可以在无须知道变量名字的情况下,间接读取或者更新变量的值。

x:=1

p:=&x  //p通过短变量声明为整形指针,指向x

*p = 2 //x = 2

每次使用变量的地址或者复制一个指针,我们就创建了新的别名或者方式来标记同一个变量,例如*px的别名,指针别名允许我们不用变量的名字来访问变量,不仅指针产生别名,当复制其他的引用类型包括含引用类型的结构体、数组、接口的值的时候,也会产生别名。

 

new()make()的区别

两者都是在堆上分配内存,但是他们行为不同,适用于不同的类型。

new()用于值类型的内存分配,并置为0值。

make()只用于切片、字典、通道这三种引用数据类型的内存分配和初始化。这三种引用类型都拥有自己的结构需要初始化。new()并不初始化结构只是分配内存。

new(T)分配类型T的零值并返回地址,也就是指向类型T的指针。

mkae(T)返回类型T的值(不是*T)。

 

go语言中并不能准确判断变量是在栈上还是在堆上分配。想知道变量分配的确切位置通过go build或者go run 时加上-m 的标志查看。

栈:存储函数中的局部变量,使用CPU管理的和优化,先进后出。

使用栈的优势不用你手动管理,读写速度也快。

堆:是计算机中一块内存区域,不会自动为你释放内存也不是CPU严格管理。在go语言中全部由垃圾回收算法自动决定。

 

 

变量的生命周期

指程序执行过程中变量存在的时间段。

包级别变量的声明周期是整个程序的执行时间。

局部变量的声明周期第动态的,每次执行声明语句创建一个新的实体,变量一直生存岛他变得不可能访问,这时他占用的存储空间被回收。

注意:局部变量是的生存时间是可以延续的,只要它的引用存在那这个变量就会一直存在(这里注意思考是否会影响程序效率增加内存负担后面会专门写)

 

func f()*int{

var x int

return &x  

}

 

 

可赋值性

包含显式赋值和隐式赋值。

类型必须精准匹配,nil可以被赋值给任何接口变量或者引用类型。

 

类型声明

type定义一个新的命名类型。

type a float64  它的底层类型是float64,相同的底层类型可以进行显示的类型转换。

如: type b float 64   a(b)进行转换。

数字类型转换,字符串和一些slice类型间的转换是允许的。这些转换将会改变值的表达形式。例如从小数点转换为整型火丢失小数部分。

 

作用域

语法块是由大括号围起来的一个语句序列,把块的概念推广到其他没有显示包括在大括号中的声明代码,将其统称为词法块。一个声明的词法块决定声明的作用域大小。一个程序可以包含多个同名的声明,前提是他们都在不同的词法块。当编译器遇到一个名字的引用时,将从最内层的封闭词法块到全局块中寻找声明。

for循环创建两个词法块,一个显式的一个隐式的。

x := “hello”

for _,x = range x{  //隐式块

//显式块

}

ifswitch也会创建隐式块

 

if x:=f(); x==0{

}else{

}

 

switch同理条件对应一个块,每个case语句对应一个块。

swith num:=3 ;num{

case 1:

……

fallthrough //继续向下执行但不在匹配条件表达式

case 2

……

default

……

}

 

类型转换

a:=10

b:=byte(a)  // intbyte

c:= a + int(b)  //混合类型表达式必须确保类型一致

不能将非bool类型当做true/false使用

 

如果要转换的类型是引用类型必须使用括号以避免语法分解错误

x:=100

p:=*int(x) //错误

正确

p:=(*int)(x)

(

(func())(b)

(func()int)(h)

 

未命名类型

与具有明确标识符的boolintstring等类型相比,数组、切片、字典、通道等类型与具体元素类型或长度等属性有关,故乘坐为命名类型。可用type为其提供具体名称,为其改变为命名类型。

 

具有相同声明的为命名类型被视为同一类型。

具有相同基类型的指针。

具有相同元素类型和长度的数组。

具有相同元素类型的切片。

具有相同键值类型的字典。

具有相同数据类型及操作方向的通道。

具有相同字段的序列(字段名、字段类型、标签、字段顺序)的结构体。

具有相同签名的函数。

具有相同方法集的接口。

你可能感兴趣的:(golang学习笔记(一))