一:Go编程语言规范--块、声明、作用域
1.块
块为一对大括号括住的声明和语句。块 = "{" { 语句 ";" } "}" .
除显式源码块外,还有隐式块:
- 全域块 包含所有的Go源码文本。
- 每个包都有包含其所有Go源码文本的 包块。
- 每个文件都有包含其所有Go源码文本的 文件块。
- 每个
if
、for
和switch
语句都被视为处于其自身的隐式块中。 - 每个
switch
或select
语句中的子句其行为如同隐式块。
块可嵌套并会影响作用域。
2.标识符
标识符被用来命名程序实体,例如变量和类型。一个标识符由一个或多个字母和数字组成。 标识符的第一个字符必须是字母。
给定一个标识符集,若其中一个标识符不同于该集中的任一标识符,那么它就是唯一的。 若两个标识符拼写不同,或它们出现在不同的包中且未 导出,那么它们就是不同的。否则,它们就是相同的。
空白标识符
空白标识符 通过下划线字符 _ 表示, 它可像其它标识符一样用于声明,但该标识符不能传入一个新的绑定。
预声明标识符
在全局块中,以下标识符是隐式声明的:
类型:
bool byte complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
常量:
true false iota
零值:
nil
函数:
append cap close complex copy delete imag len
make new panic print println real recover
已导出标识符
标识符可被 导出 以允许从另一个包访问。同时符合以下条件即为已导出标识符:
其它所有标识符均为未导出的。
关键字
以下为保留关键字,不能用作标识符。
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
3.声明和作用域
声明可将非空白标识符"_"绑定到一个常量、类型、变量、函数或包。 在程序中,每个标识符都必须被声明。
作用域 即为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。
作用域说明:
- 预声明标识符的作用域为全域块。
- 在顶级(即在任何函数之外)声明的表示常量、类型、变量或函数(而非方法)的标识符其作用域为该包块。
- 已导入包的包名作用域为包含该导入声明的文件块。
- 表示方法接收器、函数形参或返回值变量的标识符,其作用域为该函数体。
- 在函数中声明为常量或变量的标识符,其作用域始于该函数中具体常量实现或变量实现ShortVarDecl表示短变量声明)的结尾,止于最内部包含块的结尾。
- 在函数中声明为类型的标识符,其作用域始于该函数中具体类型实现的标识符,止于最内部包含块的结尾。
注意:
- 同一标识符不能在同一块中声明两次,且在文件与包块中不能同时声明。
- 在块中声明的标识符可在其内部块中重新声明。 当其内部声明的标识符在作用域中时,即表示其实体在该内部声明中声明。
- 包子句(package xxx)并非声明;包名不会出现在任何作用域中。 其目的是为了识别该文件是否属于相同的包并为导入声明指定默认包名。
标签作用域:
标签通过标签语句声明(标识符:语句),并用于 break、continue 和 goto 语句.例如:
L:
for i < n {
switch i {
case :
break L
}
}
定义不会使用的标签是非法的。与其它标识符相反,标签并不限定作用域且与非标签标识符并不冲突。 标签的作用域为除任何嵌套函数体外其声明的函数体。
4.各种声明
常量声明
const Pi float64 = 3.14159265358979323846
const zero = 0.0 // 无类型化浮点常量
const (
size int64 =
eof = - // 无类型化整数常量
)
const a, b, c = , , "foo" // a = 3, b = 4, c = "foo", 无类型化整数和字符串常量
const u, v float32 = , // u = 0.0, v = 3.0
iota
iota可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1
const ( // iota重置为0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
) const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Partyday
numberOfDays // 该常量未导出
)
在表达式列表中,每个 iota 的值都相同,因为它只在每个常量实现后增量。
const (
bit0, mask0 = << iota, <<iota - // bit0 == 1, mask0 == 0
bit1, mask1 // bit1 == 2, mask1 == 1
_, _ // skips iota == 2
bit3, mask3 // bit3 == 8, mask3 == 7
)
类型声明
声明类型不继承任何方法绑定到现存类型, 但接口类型或复合类型元素的方法集保持不变:
// Mutex为带有Lock和Unlock两个方法的数据类型.
type Mutex struct { /* Mutex字段 */ }
func (m *Mutex) Lock() { /* Lock实现*/ }
func (m *Mutex) Unlock() { /* Unlock实现*/ } // NewMutex和Mutex拥有相同的组成,但它的方法集为空.
type NewMutex Mutex // PtrMutex的基础类型的方法集保持不变.
// 但PtrMutex的方法集为空.
type PtrMutex *Mutex // *PrintableMutex的方法集包含方法
// Lock和Unlock绑定至其匿名字段Mutex.
type PrintableMutex struct {
Mutex
} // MyBlock为与Block拥有相同方法集的接口类型.
type MyBlock Block
类型声明可用来定义不同的布尔值、数字或字符串类型并对其附上方法:
type TimeZone int const (
EST TimeZone = -( + iota)
CST
MST
PST
) func (tz TimeZone) String() string {
return fmt.Sprintf("GMT+%dh", tz)
}
变量声明
变量声明将一个标识符绑定至一个创建的变量并赋予其类型和可选的初始值。
若给定一个表达式列表,则变量通过按顺序将该表达式赋予该变量(§赋值)来初始化;所有表达式必须用尽且所有变量根据它们初始化。
否则,每个变量初始化为其 零值。若该类型已存在,每个变量都赋予该类型。
否则,该类型根据该表达式列表赋值。
若该类型不存在且其对应表达式计算结果为无类型化常量, 则该声明变量的类型由其赋值描述。
实现限制:若在函数体内声明不会使用的变量,编译器可能将其判定为非法
var i int
var U, V, W float64
var k =
var x, y float32 = -, -
var (
i int
u, v, s = 2.0, 3.0, "bar"
)
var re, im = complexSqrt(-)
var _, found = entries[name] // 映射检查;只与“found”有关
短变量声明
短变量声明只能出现在函数内部。在某些情况下,例如初始化 if、 for、或 switch 语句时,它们可用来声明局部临时变量
i, j := ,
f := func() int { return }
ch := make(chan int)
r, w := os.Pipe(fd) // os.Pipe() 返回两个值
_, y, _ := coord(p) // coord() 返回三个值;只与和y同位的值相关
不同于常规变量声明,在至少有一个非空白变量时,短变量声明可在相同块中,对原先声明的变量以相同的类型重声明。 因此,重声明只能出现在多变量短声明中。 重声明不能生成新的变量;它只能赋予新的值给原来的变量。
field1, offset := nextField(str, )
field2, offset := nextField(str, offset) // 重声明 offset 在同一个块中使用var 重复声明是非法的
a, a := , // 非法:重复声明了 a,或者若 a 在别处声明,但此处没有新的变量
函数声明
函数声明可省略函数体。这样的标识符为Go外部实现的函数提供签名,例如汇编例程。
func min(x int, y int) int {
if x < y {
return x
}
return y
} func flushICache(begin, end uintptr) // 外部实现
方法声明
方法为带 接收者 的函数。方法声明将标识符,即 方法名 绑定至方法。 它也将该接收者的 基础类型 关联至该方法。
接收者类型必须为形式 T 或 *T,其中 T 为类型名。
由 T 表示的类型称为接收者的 基础类型; 它不能为指针或接口类型且必须在同一包中声明为方法。
若该接收器的值并未在该方法体中引用,其标识符可在声明中省略。这同样适用于一般函数或方法的形参。
func (p *Point) Length() float64 {
return math.Sqrt(p.x * p.x + p.y * p.y)
} func (p *Point) Scale(factor float64) {
p.x *= factor
p.y *= factor
} func (Point) Scale(factor float64) {
....
}
一:Go编程语言规范--块、声明、作用域的更多相关文章
- ES6块级作用域及新变量声明(let)
很多语言中都有块级作用域,但JS没有,它使用var声明变量,以function来划分作用域,大括号“{}” 却限定不了var的作用域.用var声明的变量具有变量提升(declaration hoist ...
- 一个经典的js中关于块级作用域和声明提升的问题
function functions(flag) { if (flag) { function getValue() { return 'a'; } } else { function getValu ...
- ES6 let const 声明变量 块级作用域
ES6 中除了使用 var 定义变量,还有let.const,定义变量. function getValue(condition){ console.log(typeof value2); // un ...
- javascript中不存在块级作用域,所以要小心使用在块级作用域中的函数声明所带来的作用域混乱.
在javascript中函数的作用域是一个非常重要的概念. javascript中是没有块级作用域,但是有函数作用域的概念. 我们在开发的过程中,经常会遇到这样的问题, 某个函数我暂时不需要,不想声明 ...
- 关于Javascript没有块级作用域和变量声明提升
Javascript是没有块级作用域的,在语句块中声明的变量将成为语句块所在代码片段的局部变量.例如: if(true){ var x=3; } console.log(x); 结果输出3. 再如: ...
- ES6-let、const和块级作用域
1.介绍 总的来说,ES6是在ES2015的基础上改变了一些书写方式,开放了更多API,这样做的目的最终还是为了贴合实际开发的需要.如果说一门编程语言的诞生是天才的构思和实现,那它的发展无疑就是不断填 ...
- 《浏览器工作原理与实践》<09>块级作用域:var缺陷以及为什么要引入let和const?
在前面我们已经讲解了 JavaScript 中变量提升的相关内容,正是由于 JavaScript 存在变量提升这种特性,从而导致了很多与直觉不符的代码,这也是 JavaScript 的一个重要设计缺陷 ...
- ECMAScript概述及浅谈const,let与块级作用域
ECMAScript可以看作javascript的标准规范,实际上javascript是ECMAScript的一门脚本语言,ECMAScript只提供了最基本的语言JavaScript对ECMAScr ...
- JavaScript模仿块级作用域
avaScript 没有块级作用域的概念.这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,来看下面的例子: function outputNumbers(count){ for ( ...
随机推荐
- java 多态奇怪现象,子类还没有构造完成就开始干活了,谁来帮我解释?
java代码: package test.extend; public class Base { public Base(){ System.out.println("基类构造") ...
- mysql hang and srv_error_monitor_thread using 100% cpu
昨天晚上,运维过来说有台生产服务器的mysql cpu一直100%,新的客户端登录不了,但是已经在运行的应用都正常可用. 登录服务器后,top -H看了下,其中一个线程的cpu 一直100%,其他的几 ...
- 手机网游开发指南 - 需要多NB的技术
Agent`K 似乎在三天打鱼N天晒网.只能呵呵了,懒散的家伙. 移动互联网越来越火,其中的网络游戏更是火,熊熊大火. 作为攻城师的你,作为小投资者的你,作为满脑子创意想要实现的你,肯定在四处打听:手 ...
- Quartz.NET开源作业调度框架系列(一):快速入门step by step
Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...
- 【Leafletjs】3.拖拽添加marker
在找leaflet和wfs的相关知识中 看到了这一效果 感觉不错: 这个效果的实现主要使用了JqueryUI的draggable和leaflet的containerPointToLatLng(可由屏 ...
- 微信小程序开发之如何哪获取微信小程序的APP ID
微信小程序的开发工具,在新建项目的时候,默认提示填写APP ID,如果不填写AppID 也是可以本地测试和开发的,但是无法通过手机调试,只能在开发工具里查看 如果需要真机调试微信小程序,需要安装微信6 ...
- Swift设置自动行高
// 设置行高自适应 tableView.rowHeight = UITableViewAutomaticDimension // 设置预估行高 tableView.estimatedRowHeigh ...
- 与TableView插入、删除、移动、多选,刷新控件
一.插入.删除.移动.多选 方法一: Cell的插入.删除.移动都有一个通用的方法,就是更新tableView的数据源,再reloadData,这样做实现上是简单一点,但是reloadData是刷新整 ...
- iOS之 C++与oc混编
声明:本文只是随笔,自己做个笔记方便以后查阅如要转载,注明出处.谢谢! 2016年第一篇随笔!!! 由于最近要搞一个项目用到c++的一些api所以要混编,于是就记录下这个过程中的一些细节上的东西! O ...
- Mac OS 下的解压缩软件——The Unarchiver
The Unarchiver 是 Mac 上最流行的解压软件,免费开源.操作方式与系统自带解压工具 Archive Utility.app 一样,双击自动解压.最爽的一点是把解压后原始文件直接仍进废纸 ...