第二章 程序结构
< P28 >
Go中的Predeclared identifiers如下:
1 | Types: |
这里面的关键字都是不保留的,可以用作我们的自定变量名,当然这是强烈不推荐的。除非已经被命名困难症逼到了绝境。
另外,变量名长度是不作限定的(the larger the scope of a name, the longer and more meanningful it should be),一个全局变量的名字应该比一个局部变量更易见名知义(所以长点也没关系)。
< P31 >
:=
(the short variable declaration)是用作声明的,而不是像=
一样用作赋值;:=
左边至少要存在一个未声明的变量;
< P35 >
如果两个变量的类型不承载任何信息,根据编译器的实现,指针地址可能相同,例如struct{}
和[0]int
;
1 | var t1 struct{} |
< P36 >
- 用生命周期长的指针指向生命周期短的变量会阻碍对该变量的GC;
- 变量被分配到堆或栈与否不由声明方式决定,如
var
或new
;(mark一下,之后再拓展一篇,如果还有机会看见这个mark)
< P39 >
显式类型转换T(x)
是一种转换(conversion),不是函数调用;
< P41 >
首先看代码:
1 | type T float64 |
那么我们在给T
实现String()
且需要打印自身时,要注意避免无穷递归调用。
< P46 >
- 变量的作用域与生命周期不相等,作用域是编译时属性(compile-time property),而生命周期是运行时属性(run-time porperty);
有或没有显式地用花括号界定的作用域都可以笼统地归纳为lexical block;例如包含整个源码的universe block,每个
package
、文件、for
、if
、switch/select
,switch/select
中的每个case
;1
2
3
4
5
6
7func main(){
x := "hello"
for _ , x := range x{ // for statement中有隐式lexical block
x := x +'A'-'a' // {}中的显式lexical block
fmt.Printf("%c",x) // 正常输出"HELLO"
}
}导入的包的作用域是file-level的,所以每个文件都要单独导入,即使是同一个包下;
- Control-flow label(用于
break
、continue
和goto
)的作用域是整个函数; - 编译器会从最内的lexical block至universe block查找变量的声明;所以最内部变量可以shadow(又或称屏蔽/hide)外部同名变量;
< P49 >
在使用:=
时要注意作用域;例如,如果要在函数内更新package-level变量,使用:=
会重新声明一个同名局部变量;
一段闲扯
!!距离拖延症发作过去了03天!!
从第二章开始的内容已经比第一章多了,不过想想,这也是肯定的。按照这个劲头,似乎半个月就能把这个系列整理完。另外hexo是真的好用,都要治好我多年的拖延症了。