1.块

块为一对大括号括住的声明和语句。块 = "{" { 语句 ";" } "}" .

除显式源码块外,还有隐式块:

    1. 全域块 包含所有的Go源码文本。
    2. 每个都有包含其所有Go源码文本的 包块
    3. 每个文件都有包含其所有Go源码文本的 文件块
    4. 每个 iffor 和switch 语句都被视为处于其自身的隐式块中。
    5. 每个 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

已导出标识符

标识符可被 导出 以允许从另一个包访问。同时符合以下条件即为已导出标识符:

    1. 标识符名的第一个字符为Unicode大写字母(Unicode类别“Lu”);且
    2. 该标识符在包块中已声明或为字段名或 方法名

其它所有标识符均为未导出的。

关键字

以下为保留关键字,不能用作标识符。

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.声明和作用域

声明可将非空白标识符"_"绑定到一个常量、类型、变量、函数或包。 在程序中,每个标识符都必须被声明。

作用域 即为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。

作用域说明:

  1. 预声明标识符的作用域为全域块。
  2. 在顶级(即在任何函数之外)声明的表示常量、类型、变量或函数(而非方法)的标识符其作用域为该包块。
  3. 已导入包的包名作用域为包含该导入声明的文件块。
  4. 表示方法接收器、函数形参或返回值变量的标识符,其作用域为该函数体。
  5. 在函数中声明为常量或变量的标识符,其作用域始于该函数中具体常量实现或变量实现ShortVarDecl表示短变量声明)的结尾,止于最内部包含块的结尾。
  6. 在函数中声明为类型的标识符,其作用域始于该函数中具体类型实现的标识符,止于最内部包含块的结尾。

注意:

  • 同一标识符不能在同一中声明两次,且在文件与包块中不能同时声明。
  • 在块中声明的标识符可在其内部块中重新声明。 当其内部声明的标识符在作用域中时,即表示其实体在该内部声明中声明。
  • 包子句(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编程语言规范--块、声明、作用域的更多相关文章

  1. ES6块级作用域及新变量声明(let)

    很多语言中都有块级作用域,但JS没有,它使用var声明变量,以function来划分作用域,大括号“{}” 却限定不了var的作用域.用var声明的变量具有变量提升(declaration hoist ...

  2. 一个经典的js中关于块级作用域和声明提升的问题

    function functions(flag) { if (flag) { function getValue() { return 'a'; } } else { function getValu ...

  3. ES6 let const 声明变量 块级作用域

    ES6 中除了使用 var 定义变量,还有let.const,定义变量. function getValue(condition){ console.log(typeof value2); // un ...

  4. javascript中不存在块级作用域,所以要小心使用在块级作用域中的函数声明所带来的作用域混乱.

    在javascript中函数的作用域是一个非常重要的概念. javascript中是没有块级作用域,但是有函数作用域的概念. 我们在开发的过程中,经常会遇到这样的问题, 某个函数我暂时不需要,不想声明 ...

  5. 关于Javascript没有块级作用域和变量声明提升

    Javascript是没有块级作用域的,在语句块中声明的变量将成为语句块所在代码片段的局部变量.例如: if(true){ var x=3; } console.log(x); 结果输出3. 再如: ...

  6. ES6-let、const和块级作用域

    1.介绍 总的来说,ES6是在ES2015的基础上改变了一些书写方式,开放了更多API,这样做的目的最终还是为了贴合实际开发的需要.如果说一门编程语言的诞生是天才的构思和实现,那它的发展无疑就是不断填 ...

  7. 《浏览器工作原理与实践》<09>块级作用域:var缺陷以及为什么要引入let和const?

    在前面我们已经讲解了 JavaScript 中变量提升的相关内容,正是由于 JavaScript 存在变量提升这种特性,从而导致了很多与直觉不符的代码,这也是 JavaScript 的一个重要设计缺陷 ...

  8. ECMAScript概述及浅谈const,let与块级作用域

    ECMAScript可以看作javascript的标准规范,实际上javascript是ECMAScript的一门脚本语言,ECMAScript只提供了最基本的语言JavaScript对ECMAScr ...

  9. JavaScript模仿块级作用域

    avaScript 没有块级作用域的概念.这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,来看下面的例子: function outputNumbers(count){ for ( ...

随机推荐

  1. 初学File类

    对File类的基本方法的理解 今天刚开始学了File类 一开始看思想编程看得迷迷糊糊的,之后受不了了,直接去看API文档 归纳: File->java.util File类的主要方法: 构造方法 ...

  2. 让你fork下来的项目与源项目保持同步

    原文在此, 建议阅读, 我把关键步骤抽出来了, 方便概览 (也就是add remote upstream, fetch upstream, rebase, 再push) Step 1: Forking ...

  3. 判断一张图片有没有src值

    我一开始一直以为判断一张图片有没有src值就是undefined呀 我知道这个 但是做起来发现出现了问题 if($('.img').attr('src') == 'undefined'){ conso ...

  4. SQL Server 跨库同步数据

    最近有个需求是要跨库进行数据同步,两个数据库分布在两台物理计算机上,自动定期同步可以通过SQL Server代理作业来实现,但是前提是需要编写一个存储过程来实现同步逻辑处理.这里的存储过程用的不是op ...

  5. Java2_J2EE、J2SE和J2ME的区别

    解析J2EE.J2SE.J2ME.JDK的区别       本文向大家简单介绍一下JDK.J2EE.J2SE.J2ME概念及区别,J2EE,J2SE,J2ME是java针对不同的的使用来提供不同的服务 ...

  6. AJAX跨域访问(从Tomcat8到Apache/Nginx)

    1.在Tomcat的Root目录下放入如下的文件 apache-tomcat-8.0.12X64\webapps\ROOT clientaccesspolicy.xml文件 <?xml vers ...

  7. DevExpress免费线上公开课17日开课

    小伙伴们,前几日DevExpress 正式发布了2015的第二次重大版本v15.2.3(更新说明),对于新版本中新增的一些功能和控件,你一定会有一些疑问,比如哪些功能是值得我们关注的,哪些控件有比较重 ...

  8. git 和 github 关系?

    1.git 和 github 是什么关系? git是一种版本控制系统.跟svn.cvs是同级的概念. github是一个网站,给用户提供git服务.这样你就不用自己部署git系统,直接用注册个账号,用 ...

  9. Fragment中的按键监听

    在Fragmentzhong中写按键监听,有两处处需要注意: 1)是否是当前显示的fragment:. 2)在所依托的activity中的onKeyDown方法处理监听事件: 其他地方和普通按键监听一 ...

  10. Android自定义View滑动事件处理总结

    滑动处理需要用到的各种工具类: android.view.VelocityTracker android.view.OverScroller android.view.ViewConfiguratio ...