Go语言圣经
  • 前言
  • Go语言起源
  • Go语言项目
  • 本书的组织
  • 更多的信息
  • 致谢
  • 入门
    • Hello, World
    • 命令行参数
    • 查找重复的行
    • GIF动画
    • 获取URL
    • 并发获取多个URL
    • Web服务
    • 本章要点
  • 程序结构
    • 命名
    • 声明
    • 变量
    • 赋值
    • 类型
    • 包和文件
    • 作用域
  • 基础数据类型
    • 整型
    • 浮点数
    • 复数
    • 布尔型
    • 字符串
    • 常量
  • 复合数据类型
    • 数组
    • Slice
    • Map
    • 结构体
    • JSON
    • 文本和HTML模板
  • 函数
    • 函数声明
    • 递归
    • 多返回值
    • 错误
    • 函数值
    • 匿名函数
    • 可变参数
    • Deferred函数
    • Panic异常
    • Recover捕获异常
  • 方法
    • 方法声明
    • 基于指针对象的方法
    • 通过嵌入结构体来扩展类型
    • 方法值和方法表达式
    • 示例: Bit数组
    • 封装
  • 接口
    • 接口是合约
    • 接口类型
    • 实现接口的条件
    • flag.Value接口
    • 接口值
    • sort.Interface接口
    • http.Handler接口
    • error接口
    • 示例: 表达式求值
    • 类型断言
    • 基于类型断言识别错误类型
    • 通过类型断言查询接口
    • 类型分支
    • 示例: 基于标记的XML解码
    • 补充几点
  • Goroutines和Channels
    • Goroutines
    • 示例: 并发的Clock服务
    • 示例: 并发的Echo服务
    • Channels
    • 并发的循环
    • 示例: 并发的Web爬虫
    • 基于select的多路复用
    • 示例: 并发的字典遍历
    • 并发的退出
    • 示例: 聊天服务
  • 基于共享变量的并发
    • 竞争条件
    • sync.Mutex互斥锁
    • sync.RWMutex读写锁
    • 内存同步
    • sync.Once初始化
    • 竞争条件检测
    • 示例: 并发的非阻塞缓存
    • Goroutines和线程
  • 包和工具
    • 包简介
    • 导入路径
    • 包声明
    • 导入声明
    • 包的匿名导入
    • 包和命名
    • 工具
  • 测试
    • go test
    • 测试函数
    • 测试覆盖率
    • 基准测试
    • 剖析
    • 示例函数
  • 反射
    • 为何需要反射?
    • reflect.Type和reflect.Value
    • Display递归打印
    • 示例: 编码S表达式
    • 通过reflect.Value修改值
    • 示例: 解码S表达式
    • 获取结构体字段标识
    • 显示一个类型的方法集
    • 几点忠告
  • 底层编程
    • unsafe.Sizeof, Alignof 和 Offsetof
    • unsafe.Pointer
    • 示例: 深度相等判断
    • 通过cgo调用C代码
    • 几点忠告
  • 附录
    • 附录A:原文勘误
    • 附录B:作者译者
    • 附录C:译文授权
    • 附录D:其它语言
Powered by GitBook
On this page

Was this helpful?

  1. 程序结构

命名

Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线。大写字母和小写字母是不同的:heapSort和Heapsort是两个不同的名字。

Go语言中类似if和switch的关键字有25个;关键字不能用于自定义名字,只能在特定语法结构中使用。

break      default       func     interface   select
case       defer         go       map         struct
chan       else          goto     package     switch
const      fallthrough   if       range       type
continue   for           import   return      var

此外,还有大约30多个预定义的名字,比如int和true等,主要对应内建的常量、类型和函数。

内建常量: true false iota nil

内建类型: int int8 int16 int32 int64
          uint uint8 uint16 uint32 uint64 uintptr
          float32 float64 complex128 complex64
          bool byte rune string error

内建函数: make len cap new append copy close delete
          complex real imag
          panic recover

这些内部预先定义的名字并不是关键字,你可以再定义中重新使用它们。在一些特殊的场景中重新定义它们也是有意义的,但是也要注意避免过度而引起语义混乱。

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

名字的长度没有逻辑限制,但是Go语言的风格是尽量使用短小的名字,对于局部变量尤其是这样;你会经常看到i之类的短名字,而不是冗长的theLoopIndex命名。通常来说,如果一个名字的作用域比较大,生命周期也比较长,那么用长的名字将会更有意义。

在习惯上,Go语言程序员推荐使用 驼峰式 命名,当名字有几个单词组成的时优先使用大小写分隔,而不是优先用下划线分隔。因此,在标准库有QuoteRuneToASCII和parseRequestLine这样的函数命名,但是一般不会用quote_rune_to_ASCII和parse_request_line这样的命名。而像ASCII和HTML这样的缩略词则避免使用大小写混合的写法,它们可能被称为htmlEscape、HTMLEscape或escapeHTML,但不会是escapeHtml。

Previous程序结构Next声明

Last updated 4 years ago

Was this helpful?