1 for range循环的时候会创建每个元素的副本 而不是元素的引用 所以m[key] = &val取得是变量val得地址,所以最后map中所有元素得值都是变量val的地址,
2 new(T)会为T类型的新值分配已置零的内存空间,并返回地址(指针),即类型为*T的值,换句话说就是,返回一个指针,该指针指向新分配的,类型为T的零值,适用于值类型,如数组,结果体等
make(t,args)返回初始化之后的T类型的值,这个值并不是T类型的零值,也不是指针*T,是经过初始化之后的T的引用,make()只使用于slice,map和channel.
3 append()的第二个参数不能直接使用slice,需用...操作符,将一个切片追加到另一个切片上,append(s1,s2...)。或者直接上元素 append(s1,2,3)
4 new([]int)之后的list是一个*[]int类型的指针,不能对指针执行append操作,可以使用make()初始化之后再使用,同样的,map和channel建议使用make()进行字面量的初始化
5 x := 100 1必须使用显式初始化 2 不能提供数据类型 编译器自动推导 3 只能在函数内部使用简短模式
6 结构体只能比较是否相等,但是不能比较大小
相同类型的结构体才能进行比较,结构体是否相同不但与属性有关,还与属性顺序有关,sn3与sn1就是不同的结构体
7 如果struc的所有成员都可以比较,则该struct就可以通过==或!=进行比较是否相等,比较时逐项进行比较,如果每一i昂相等,则两个结构体才相等,否则不相等
可比较的有:bool,数值符,字符,指针,数组 不能比较的是有切片 map和函数
8 type MyInt int 创建了新类型MyInt1
type MyInt2 = int 创建了一个类型别名 可以赋值
9 连接字符串的方法
str := "abc" + "123"
fmt.Sprint("abc%d",123)
strings.Join( )
buffer.WriterString()
10 nil只能赋值给指针,chan,func,interface,map和slice。。。error类型是一种内置接口类型
11 init() 函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等;一个包可以出线多个 init() 函数,一个源文件也可以包含多个 init() 函数;同一个包中多个 init() 函数的执行顺序没有明确定义,但是不同包的init函数是根据包导入的依赖关系决定的(看下图);init() 函数在代码中不能被显示调用、不能被引用(赋值给函数变量),否则出现编译错误;一个包被引用多次,如 A import B,C import B,A import C,B 被引用多次,但 B 包只会初始化一次;引入包,不可出现死循坏。即 A import B,B import A,这种情况编译失败
12 hello()的变量是nil,将hello()赋值给h,而不是函数的返回值,所以h not nil
13 i.(type),其中i是接口,type是固定关键字,只有接口类型才可以使用类型选择
14 声明channel : var ch chan int
ch := make(chan int)
读channel : <- ch
写channel : ch <- n 写chan必须带上值
15 i.(type),其中i是接口,type是固定关键字,只有接口类型才可以使用类型选择
16 声明channel : var ch chan int
ch := make(chan int)
读channel : <- ch
写channel : ch <- n 写chan必须带上值
17 打印一个map中不存在的值时,会返回元素的零值 不同类型的数值不能相加 如int float
18 操作符[i,j].基于数组(切片)可以使用操作符[i,j]创建新的切片,从索引i到索引j结束,截取已有数组(切片)的任意部分,返回新的切片,新切片的值包含原数组(切片)的i的索引的值,但是不包含j索引的值,i,j都是可选的,如果i省略那么默认是0,j如果省略,默认是数组的长度,且i,j都不能超过这个长度值
加入底层数组的大小为k,截取之后获得的切片的长度和容量的计算方法 长度i-j,容量 k-i
截取操作符还有第三个参数,形如[i.j.k]第三个参数用来限制新切片的容量,但不能超过原数组(切片)的的大小,截取的切片的长度和容量分别是 j-i,k-i
19 数组是值类型,可以比较,但是 数组的长度是数组类型的组成部分,数组长度不同即数组类型不同。不能比较
20 cap()函数不能适用于map,可用于array,slice,channel
21 当且仅当接口的动态值和动态类型都是nil时,接口类型才是nil
22 删除map不存在的键值对时,不会报错,相当于没有作用,获取不存在的键值对时,返回值类型对应的时零值,所以返回0
23 通过嵌套,内部类型的的属性,方法可以被外部类型所有,就好像外部类型自己的一样,此外,外部类型还可以定义自己的属性和方法,甚至可以定义与内部相同的方法,这样内部类型的方法就会被“屏蔽”
24 Go中的字符串就是只读的
25 incr()函数里的P是*int类型的指针,指向的是main()函数点变量p的指针
26 var sa []int 是nil切片
var sb = []int{} 是空切片
nil切片和nil相等,一般用来表示一个不存在的切片,空切片和nil不相等表示一个空的集合
27 一个类型实现多个接口,结构体Work分别实现离开接口A,B,所以接口a,b,调用各自的方法ShowA()和Show()
28 当多值赋值时,:=左边的变量无论声明与否都可以
29 被调用函数里的defer语句在返回之前就会被执行
30 函数参数为interface{}时可以接收任何类型的参数,包括用户自定义类型等,即使接收指针类型也用interface{}
永远不要使用一个指针指向一个接口类型,因为它已经是一个指针
30 golang的字符串类型是不能赋值nil的,也不能和nil进行比较
31 defer关键字后面的函数或者方法想要执行必须先注册,return之后的defer是不能注册的,也不能执行后面的函数和方法
32 基于类型创建的方法必须创建在同一个包内,所以,类型与方法不在同一个包内就会编译出错
33 值类型和指针类型*Student实现方法是不一样的
34 对于x=y的赋值操作,必须知道x的地址,才能够将y的值赋给x,go中的map的value本身是不可寻址的
35 操作符:=,对于使用:=定义的变量,如果新变量与同名已定义的变量不在同一个作用域中,那么Go会重新定义这个变量,main()函数里的P是新定义的变量,会遮住全局变量p
36 for range使用短变量声明(:=)的形式迭代变量,变量i,v在每次循环体中会被重用,而不是重新声明
各个groutine输出的i,v值都是for range循环结束后的i,v最终值,而不是各个grooutine启动时的i,v值,可以理解为闭包引用,使用的是上下环境的值
37 协程比和线程都可以实现程序的并发执行
通过channel来进行协程间的通信
for循环支持continue和break来控制循环,但是它提供了一个更高级的break,来选择中断哪一个循环
for循环不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方法来初始化多个变量
i++和i--在Go语言中是语句,不是表达式,因此不能赋值给另外的变量,没有++i和-i
38 channel特性:
给一个nil channel发送数据,造成永远阻塞
从一个nil channel接收数据,造成永远阻塞
给一个已经关闭的channel发送数据,引起panic
从一个已经关闭的channel接收数据,如果缓冲区中为空,则返回一个零值
无缓冲的channel是同步的,而有缓冲的channel是非同步的
39 常量不同于变量的在运行期分配内存,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用,所以常量无法寻址
40 nil可以用作interface,function,poniter,map,slice和channel的空值,但是如果不特别声明指定的话,Go语言不能识别类型
41 创建User的类型别名,可以使用=定义类型别名,是别名则完全等价于User,具有User的所有方法
42 select机制用来处理异步IO问题
select机制最大的一条限制就是每个case语句中必须是以io操作
43 map需要初始化之后才能正常使用,指针不支持索引
44 (p *int)p是指针变量,*p++操作的意思是取出变量v的值并执行加一操作,所以v的最终值是2
45 如果有未使用的变量代码将编译失败,有例外,函数中声明的变量必须要使用,但可以有未使用的全局变量,函数的参数未使用也是可以的。
如果是给未使用的变量分配一个新的值,代码也是会编译失败,需要在某个地方使用这个变量,才能让编译器编译
46 导入的包没有被使用,如果引入一个包,但是未使用其中如何函数,接口,结构体或变量的话,代码将编译失败,如果真的需要引入包,可以使用下划线操作符,_,来作为这个包的名字,从而避免失败,下划线操作符用于引入,但不使用,我们可以注释或者移除未使用的包
47 不能对nil的map直接赋值,需要使用make()初始化,但可以使用append()函数为nil的slice增加元素
48 使用cap()获取map()的容量, 使用make变量时可以指定第二个参数,不过会被忽略,cap()函数会适用于数组,指针,slice和channel,不适用于map,可以适用len()返回map的元素个数
49 常量是一个简单值得标识符,在程序运行时,不会修改得量,不像变量,常量未使用时能编译通过的
50 使用变量简短声明符号:=时,如果符号左边有多个变量,只需要保证至少有一个变量时新声明的,并对已定义的变量进行赋值操作,但如果出现作用域之后,就会导致变量隐藏的问题
51 Go里面采用的是^,按位取反之后每个bit位都取反的数,对于有符号的整数来说,是按照补码进行取反操作的(快速计算方法,对数a取反),对于无符号整数来说都是按位取反如果作为二元运算符,^表示按位异或,即:对应位相同为0,相异为1
52 操作符&^,按位置零,例如 z=x &^ y,表示如果y中的bit为1,则z对应的bit位为0,否则z对应bit位等于x中相应的bit位的值
或操作符| 例如 z= x | y如果y中的bit位为1,则对应的bit位为1,否则对应bit位等于x中相应的bit位的值
53 函数之间不能互相比较,只能和nil比较 || map中的val是不可寻址的,所以无法直接赋值
54 在方法中,指针类型的接收者必须是合法指针(包括nil),或能获取实例地址
55 检查map是否含有某一元素,直接判断元素的值不是一种合适的方式,最可靠的是使用访问map时返回的第二个值
56 recover()函数必须在defer()函数调用中才有效,所以其它捕获是无效的,在调用defer()时,会计算函数的参数并压入栈中
57 for range 循环数组,此时使用的数组是副本,所以对此时使用的数组赋值操作不会影响到原数组
58 for-range数组指针,for-range循环中的循环变量t是原数组元素的副本,如果数组元素是结构体值,则副本的字段和原数组字段是两个不同的值
59 for-range切片,for-range切片使用的是切片的副本,但不会复制底层数组,此副本与原数组共享底层数组
60 defer(),for-range,for-range虽然使用的是:=,但是v不会被重新声明
61 单引号,双引号和字符串连接,在Go语言中,双引号用来表示字符串string,其实质是一个byte类型的数组,单引号表示rune类型
62 string(),是指针方法,而不是值方法,所以使用Pringtln()输出时不会调用String()方法
63 闭包延迟求值,for循环局部变量i,匿名函数每一次使用的都是同一个变量
64 当程序出现for{}时,会独占cpu资源,导致其它Goroutine饿死
65 xxxxxxxxxx 简短声明变量,只能作用于函数内部短变量声明语句中至少要声明一个变量
66 defer()语句应该放在if()语句前面,先判断err,再defer关闭文件句柄
67 panic,recover(),当程序panic时就不会向下执行,可以使用recover()捕获panic的内容
68 wg := sync.WaitGroup() 协程里面,wg.Add(),wg.Wait(),wg.Done()是成批存在的,否则会导致panic()
69 cap()函数的作用:1
arry返回数组的元素个数
slice返回slice的最大容量
channel返回channel的容量
70 可变函数都是指针传递
71 switch语句中,单个case中,可出现多个结果选项,只有再case中明确添加fallthrough关键字,才会执行紧跟的下一个case
72 类型的String()方法。如果类型定义了String()方法,使用Panic(),Print(),Println(),Sprintf()等格式化输出时会自动使用String()方法
73 计算等号左边的指针索引表达式和取址表达式,接着计算等号右边的表达式
74 Go语言中的内存回收机制规定,只要有一个指针指向引用一个变量,那么这个变量就不会被释放(内存逃逸),因此在Go语言中返函数打或临时变量是安全的
75 byte是uint8的别名,范围是0-128,超过则会产生数值溢出
76 在一个常量声明代码块中,如果iota没出现在第一行,则iota常量的初始值就是非0值
77 一个文件夹只能是一个包,可以多个.go文件,但这些文件必须属于同一个包
78 由panic引发异常之后,程序停止运行,然后调用延迟函数(defer) 就像程序正常退出一样
79 TrimRught()会将第二个参数字符串里面所有的字符拿来处理,只要与其中任何一个字符相等,便会将其删除,想正确的截取字符串
80 coopy(dst,src)函数返回len(dst),len(src)之间的最小值,如果想要将src完全拷贝至dst,必须给dst分配足够的内存空间
81 for循环开始的时候,终止条件只会计算一次
82 不同类型的值是不能相互赋值的,即使底层类型一样,对于底层类型相同的变量可以相互赋值还有一个重要的条件,即只要有一个不是有名类型(named type)
83 Named Type有两类:
1内置类型 比如int,int64,float,string,bool
2 使用关键字type声明的类型
84 除了init()函数之外,一个包不允许有其它同名函数,init()函数不能杯其它函数调用,包括main()函数
85 用copy()函数的功能,切片复制,并且返回两者长度的较小值
86 Go语言里没有引用变量,每一个变量都占用一个唯一的内存地址,所以第一个比较输出false
87 get()函数返回的切片与公用切片公用底层数组,如果在调用函数里面修改返回的切片,将会影响到原切片
88 for语句的变量a是重新声明,它的作用范围只在for语句范围内
89 true是预定义标识符可以用作变量名
90 遍历map是无序的
91 在执行Get()方法时可能会报错,读写锁,虽然可以使用sync.Mutex做写锁,但是map是并发读写不安全的,map属于引用类型,并发读写时多个协程是通过指针访问同一个地址,即访问共享变量,此时同时读写资源存在竞争关系,会报错
92 for循环支持continue和break来控制循环,但是它提供了一个更高级的break,可以选择中断哪一个循环
for循环不支持以逗号为间隔的多个赋值语句,必须使用平行赋值来初始化多个变量
break会跳出select块,但不会跳出for循环,但是可以使用break label和goto来跳出for循环
93 无缓存通道需要一直有接收者接收数据,写操作才会继续,不然会一直阻塞,而缓冲为n则即使没有接收者也不会阻塞,因为缓冲大小为n,只有当放第n+1个值得时候,前n个都没有被拿走,这时候才会被阻塞
94 函数得return value不是原子操作,而是编译器分解成两部分,返回值赋值和return
95 当写锁阻塞时,新的读锁时无法申请得,导致死锁
96 WaitGroup在调用Wait()之后不能再调用Add()方法
97 加锁之后复制变量,会将锁的状态也复制
98 单引号,双引号和字符串连接,在Go语言中,双引号用来表示字符串string,其实质是一个byte类型的数组,单引号表示rune类型
99 如果有未使用的变量代码将编译失败,有例外,函数中声明的变量必须要使用,但可以有未使用的全局变量,函数的参数未使用也是可以的。
如果是给未使用的变量分配一个新的值,代码也是会编译失败,需要在某个地方使用这个变量,才能让编译器编译
100 for range使用短变量声明(:=)的形式迭代变量,变量i,v在每次循环体中会被重用,而不是重新声明
各个groutine输出的i,v值都是for range循环结束后的i,v最终值,而不是各个grooutine启动时的i,v值,可以理解为闭包引用,使用的是上下环境的值
版权声明:本文为m0_58181788原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。