Go语言入门:程序结构 | 青训营

62 阅读4分钟

命名

Go语言程序员推荐使用 驼峰式 命名,缩略词则避免使用大小写混合的写法

名字在函数内部定义,就只在函数内部有效;在函数外部定义,在当前包的所有文件中都可以访问。

名字的开头字母的大小写决定了名字在包外的可见性。大写字母开头的(译注:必须是在函数外部定义的包级名字;包级函数名本身也是包级名字),那么它将是导出的,也就是说可以被外部的包访问,例如fmt包的Printf函数就是导出的,可以在fmt包外部访问。包本身的名字一般总是用小写字母

声明

var、const、type和func,分别对应变量、常量、类型和函数实体对象的声明

包一级声明语句声明的名字可在整个包对应的每个源文件中访问,局部声明的名字就只能在函数内部很小的范围被访问

变量

变量声明的一般语法如下:var 变量名字 类型 = 表达式(go语言中类型都在名字后),“类型”或“= 表达式”两个部分可以省略其中的一个

在Go语言中不存在未初始化的变量,接口或引用类型(包括slice、指针、map、chan和函数)变量对应的零值是nil

var i, j, k int                 // int, int, int
var b, f, s = true, 2.3, "four" // bool, float64, string

简短变量声明

可用于声明和初始化局部变量。它以 名字 := 表达式 形式声明变量,变量的类型根据表达式来自动推导

也可用来声明和初始化一组变量:

i, j := 0, 1
  • “:=”是一个变量声明语句
  • “=”是一个变量赋值操作

简短变量如果语句声明过了,那么简短变量声明语句对这些已经声明过的变量就只有赋值行为了,简短变量声明语句中必须至少要声明一个新的变量

指针

&x 取x变量的内存地址

*p 读取指针指向的变量的值

x := 1
p := &x         // p, of type *int, points to x
fmt.Println(*p) // "1"
*p = 2          // equivalent to x = 2
fmt.Println(x)  // "2"

new函数

new(T) 将创建一个T类型的匿名变量,初始化为T类型的零值,然后返回变量地址,返回的指针类型为*T

赋值

person.name = "bob"         // 结构体字段赋值
count[x] = count[x] * scale // 数组、slice或map的元素赋值
// 上行赋值语句等价于
count[x] *= scale           // 特定的二元算术运算符和赋值语句的复合操作 简洁形式

++,--是语句,而不是表达式,因此 x = i++之类的表达式是错误的

元组赋值

是另一种形式的赋值语句,它允许同时更新多个变量的值。在赋值之前,赋值语句右边的所有表达式将会先进行求值,然后再统一更新左边对应变量的值

x, y = y, x // 交换两个变量的值

// 计算两个整数值的的最大公约数
func gcd(x, y int) int {
    for y != 0 {
        x, y = y, x%y
    }
    return x
}

可赋值性

隐式赋值行为

medals := []string{"gold", "silver", "bronze"}
// 等价于
medals[0] = "gold"
medals[1] = "silver"
medals[2] = "bronze"

类型

一个类型声明语句创建了一个新的类型名称,和现有类型具有相同的底层结构:type 类型名字 底层类型。类型声明语句一般出现在包一级,因此如果新创建的类型名字的首字符大写,则在包外部也可以使用

对于每一个类型T,都有一个对应的类型转换操作 T(x),用于将 x 转为 T 类型

包和文件

每个源文件都是以包的声明语句开始,用来指明包的名字

包级别的名字,例如在一个文件声明的类型和常量,在同一个包的其他源文件也是可以直接访问的,就好像所有代码都在一个文件一样

导入包

在Go语言程序中,每个包都有一个全局唯一的导入路径。导入语句中类似"gopl.io/ch2/tempconv"的字符串对应包的导入路径。一个导入路径代表一个目录中的一个或多个Go源文件

每个包还有一个包名,包名一般是短小的名字(并不要求包名是唯一的),包名在包的声明处指定。按照惯例,一个包的名字和包的导入路径的最后一个字段相同,例如 ch2/tempconv 包的名字一般是tempconv

如果导入了一个包,但是又没有使用该包将被当作一个编译错误处理

包的初始化

可以用表达式初始化,也可以用 init 初始化函数,每个文件可包含多个 init 初始化函数