Golang 基础知识

标识符

  • 如果标识符在函数内部定义,那么它只在函数内部有效。
  • 如果标识符在函数外部定义,那么它在当前包的所有源文件中都可以访问,它在包外的可见性则取决于该标识符的首字母的大小写,
    • 具体地说,如果标识符以大写字母开头的,则称它是导出的,也就是说可以被外部的包访问。例如 fmt 包的 Printf 函数就是导出的,因此可以在除了 fmt 包之外的其他包中访问它。

Golang 标识符命名习惯:

  • 包名一般总是用小写字母,例如 fmt 包、strings 包和 math 包等。
  • 变量通常使用驼峰式命名,当变量名由多个单词组成时优先使用大小写分隔,而不是用下划线分隔,例如 camelCase

声明语句

Golang 中有四种类型的声明语句,分别是变量声明var)、常量声明const)、类型声明type)和函数声明func)。

变量声明

变量声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值。

变量声明使用 var 关键字,声明示例如下:

1// 完整变量声明
2var i int = 1

变量声明中可以省略类型或者初始值,但不能同时省略:

1// 变量声明,省略类型,实际类型由初始值推导出来
2var j = 2
3
4// 变量声明,省略初始值,使用该类型的零值进行初始化
5var f float

如果在变量声明中省略初始值,则使用零值初始化,例如 intfloatboolstringlistmap 类型的零值分别为 00.0false””[]{} 。零值初始化机制可以确保每个被声明的变量都能有一个初始值。

可以在一条声明语句中同时声明多个变量,或用一组初始化表达式声明并初始化一组变量。如果省略每个变量的类型,将可以声明多个类型不同的变量(类型由初始化表达式推导):

1// 同时声明多个同类型变量,零值初始化
2var i, j, k int
3
4// 同时声明多个不同类型变量,手动初始化
5var b, f, s = false, 1.23, "Hello, World!"

简短变量声明语句中必须至少要声明一个新的变量:

  • 变量名采用驼峰命名法
  • 变量名首字符是否大写控制了访问性:大写表示包外可见
  • golang 支持类型推断,因此大部分情况下可以省略类型
  • var 关键字用于声明局部变量、包变量、块声明。

声明一个变量有好几种方式,下面这些都等价:

1s := ""
2var s string
3var s = ""
4var s string = ""
  • 第一种形式,是一条短变量声明,最简洁,但只能用在函数内部,而不能用于包变量。

  • 第二种形式依赖于字符串的默认初始化零值机制,被初始化为 “"。

  • 第三种形式用得很少,除非同时声明多个变量。

  • 第四种形式显式地标明变量的类型,当变量类型与初值类型相同时,类型冗余,但如果两者类型不同,变量类型就必须了。

    实践中一般使用前两种形式中的某个,初始值重要的话就显式地指定变量的类型,否则使用隐式初始化。

注:

  • Golang 不允许使用无用的局部变量,如果需要可以使用空标识符 _ 。例如在 for 循环里,丢弃不需要的循环索引,只保留元素值,示例如下:

    1var nums []int = [1, 3, 5, 7, 9]
    2for _, num := range nums {
    3    fmt.Println(num)
    4}
    

常量声明

常量声明语句使用 const 关键字,常量必须显式初始化,且初始化完成之后不能再被修改,例如:

1const PI = 3.14
  • const 关键字用于声明常量,必须显示初始化,不能被修改。
  • 常量命名方式通常采用全大写(e.g. PI)或者驼峰命名法(e.g. ErrorCode)。

类型声明

Golang 是强类型的编程语言,即每个变量都必须具有一个类型。使用类型声明语句可以基于已有类型创建出一个新的类型,类型声明语句使用 type 关键字,例如:

1// 为 int 指针类型定义一个别名 intPtr
2type intPtr *int
3
4// 为 int 数组类型定一个别名 nums
5type nums []int

注:

  • 如果两个变量的底层类型相同,但是类型名称不相同,它们也是不兼容的类型。

函数声明

函数声明语句使用 func 关键字,例如:

1func hello(name string) string {
2    return fmt.Sprintf("Hello, %s!", name)
3}

指针

new 函数

另一个创建变量的方法是调用内建的 new 函数,表达式 new(T) 将创建一个 T 类型的匿名变量,初始化为 T 类型的零值,然后返回变量地址,返回的指针类型为 *T ,例如:

1// 变量 p 是一个 int 类型的指针
2var p *int = new(int)
3
4// 变量 q 是一个 string 类型的指针
5var q = new(string)

运算符及其优先级

注:

  • Golang 中不存在三目运算符 ?:
  • Golang 中自增、自减只支持 i++i-- 后缀形式,不支持 ++i--i 前缀形式。

注释

Golang 支持单行注释和多行注释, 单行注释使用 //,多行注释使用 /*..*/ ,示例如下:

1// This is a single line comment.
2
3/*
4  This is a multi-line comment.
5  This is a line.
6  This is another line.
7*/

注:

  • Golang 注释不能嵌套

总结

  • Golang 中标识符的可见性通过首字母的大小写控制,首字母大写的标识符会从定义它们的包中被导出,首字母小写的则不会。这种限制包内成员的方式同样适用于结构体或者一个类型的方法,因而如果我们想要封装一个对象,我们必须将其定义为一个 struct。这种基于名字的手段使得在语言中最小的封装单元是 package,而不是像其它语言一样的类型。一个 struct 类型的字段对同一个包的所有代码都有可见性,无论你的代码是写在一个函数还是一个方法里。