名称与声明

  1. go中的名称开头是一个字母或下划线,后面可以跟任意数量的字符、数字和下划线,并区分大小写
  2. 风格上,当遇到由单词组成的名称时,go程序员一般使用“驼峰式”的风格——更喜欢使用大写字母而不是下划线
  3. var声明创建一个具体类型的变量,然后给它附加一个名字,设置一个初始值,每一个声明有一个通用的形式:
     var name type=expression
    

    类型和表达式部分可以省略一个,但是不能都省略。表达式省略的话初始值就是类型的零值

  4. 忽略类型使用表达式初始化允许声明多个不同类型的变量。包级别的变量初始化在main函数开始之前进行,局部变量初始化和声明一样在函数执行期间
  5. 短变量声明可以用来声明和初始化局部变量,使用name:=expression的形式,变量类型由表达式类型决定。多变量的声明不能和多变量的赋值搞混。
  6. 短变量声明不需要声明所有在左边的变量,如果一些变量在同一个词法块中声明,那么对于这些变量,短声明的行为等同于赋值。短变量声明最少声明一个新变量,否则代码编译无法通过
  7. 代表变量的表达式,是唯一可以应用取地址符&的表达式。函数返回局部变量的地址是非常安全的。每次都会返回一个不同的值。
  8. 另一种创建指针变量的方式是使用内置的new函数,表达式new(T)创建一个未命名的T类型变量,初始化为T类型的零值,并返回其地址
  9. 每一次调用new返回一个具有唯一地址的不同变量,这个规则有一个例外:两个变量的类型不携带任何信息且是零值时,例如struct{}[0]int,当前的实现里面它们有相同的地址
  10. new只是预声明的函数,不是一个关键字,所以它可以重定义为另外的其他类型

变量与声明周期

  1. 包级别变量的生命周期是整个程序的执行时间,相反局部变量有一个动态的生命周期:执行声明语句时创建一个新的实体,变量一直生存到它变得不可访问,这时它占用的存储空间被回收
  2. 因为变量的生命周期是通过它是否可达来确定的,所以局部变量可在包含它的循环的一次迭代之外继续存活。即使包含它的循环已经返回,它的存在还可能延续
  3. 编译器可以选择使用堆或栈上的空间来分配,这个选择不是基于使用var或new关键字来声明变量,而是使用global关键字会强制使用堆空间
  4. 多重赋值允许几个变量一次性被赋值,在实际更新变量前,右边所有的表达式被推演,当变量同时出现在赋值符的两侧时特别有用,比如交换变量时:x,y=y,x
  5. 赋值只有在值对于变量类型是可赋值的时才合法,可赋值性对于不同类型有着不同的规则
  6. type声明定义一个新的命名类型,它和某个已有类型使用同样的底层类型,命名类型提供了一种方式来区分底层类型的不同或者不兼容使用,这样它们就不会在无意中混用
  7. 类型的声明如果是导出的(开头使用大写字母)。其他的包也可以访问它(其他开头大写的导出变量也一样)
  8. 对于每个类型T,都有一个对应的类型转换操作T(x)将值x转换为类型T,如果两个类型具有相同的底层类型或者二者都是指向相同底层类型变量的未命名指针类型,则二者是可以相互转换的。类型转换不改变类型值的表达方式,仅改变类型
  9. 命名类型的底层类型决定了它的结构和表达方式,以及它支持的内部操作集合,这些内部操作与直接使用底层类型的情况相同
  10. 命名类型的值可以与其相同类型的值或者底层类型相同的未命名类型的值进行比较,但是不同命名类型的值不能直接比较,即使他们底层类型一样也不行,需要使用类型转换
  11. 方法名出现在类型的后面表明这个方法关联到这个类型

包和文件

  1. 每一个包给它的声明提供独立的命名空间,包让我们可以通过控制变量在包外面的可见性或导出情况来隐藏信息,go通过一条简单的规则来管理标识符是否对外可见:导出的标识符以大写字母开头
  2. 在go程序中,每一个包通过称为导入路径的唯一字符串来标识。导入声明可以给导入的包绑定一个短名字,用来在整个文件中引用包的内容
  3. 包的初始化从初始化包级别的变量开始,这些变量按照声明顺序初始化,在依赖已解析完毕的情况下依据依赖的顺序进行
  4. 对于其他一些变量,比如数据表,初始化表达式不是简单地设置它的初始化值。这种情况下,init函数的机制会比较简单。任何文件可以包含任意数量的init函数。这个函数不能被调用或引用
  5. 包的初始化按照在程序中导入的顺序来进行,依赖顺序优先,每次初始化一个包,初始化过程是自下向上的,main包最后初始化
  6. 声明的作用域是声明在程序文本中出现的区域,它是一个编译时属性,变量的声明周期是变量在程序执行期间能被程序的其他部分所引用的起止时间,它是一个运行时属性
  7. 一个声明的词法块决定声明的作用域大小。导入的包是文件级别的,只能在同一个文件中被引用。
  8. 多个if-else语句时,第二个if语句嵌套在第一个中,所以第一个语句的初始化部分声明的变量在第二个语句中是可见的,同样的规则可以应用于switch语句:条件对应一个块,每个case语句体对应一个块
  9. 在包级别,声明的顺序和它们的作用域没有关系,所以一个声明可以引用它自己或是它后面的其他声明,使我们可以声明递归或相互递归的类型和函数。如果常量或变量声明引用它自己则编译器会报错
  10. 有变量未使用或者有导入的包未使用,编译器都会报错。