Skip to content

Commit 4a5ec7d

Browse files
committed
Merge pull request astaxie#99 from chenwenli/master
update 2.2md
2 parents 44d92a5 + 3e610a9 commit 4a5ec7d

File tree

4 files changed

+52
-50
lines changed

4 files changed

+52
-50
lines changed

2.2.md

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# 2.2 Go基础
22

3-
这小节我们将要介绍如何定义变量、常量、Go内置类型以及一些Go程序设计中的技巧
3+
这小节我们将要介绍如何定义变量、常量、Go内置类型以及Go程序设计中的一些技巧
44

55
## 定义变量
66

77
Go语言里面定义变量有多种方式。
88

9-
使用`var`关键字定义变量是最基本的,与C语言定义变量不同的是,Go语言变量名在变量类型前面
9+
使用`var`关键字是Go最基本的定义变量方式,与C语言不同的是Go把变量类型放在变量名后面
1010

1111
//定义一个名称为“variableName”,类型为"type"的变量
1212
var variableName type
@@ -29,7 +29,7 @@ Go语言里面定义变量有多种方式。
2929
*/
3030
var vname1, vname2, vname3 type= v1, v2, v3
3131

32-
你是不是觉得上面这样的定义有点复杂?没关系,因为Go语言的设计者也发现了,我们来让它变得简单一点。我们可以直接忽略类型声明,那么上面的东西变成这样了
32+
你是不是觉得上面这样的定义有点繁琐?没关系,因为Go语言的设计者也发现了,有一种写法可以让它变得简单一点。我们可以直接忽略类型声明,那么上面的代码变成这样了
3333

3434
/*
3535
定义三个变量,它们分别初始化相应的值
@@ -38,7 +38,7 @@ Go语言里面定义变量有多种方式。
3838
*/
3939
var vname1, vname2, vname3 = v1, v2, v3
4040

41-
你还是觉得上面的有些复杂?好吧,我觉得也是。让我们继续简化:
41+
你觉得上面的还是有些繁琐?好吧,我也觉得。让我们继续简化:
4242

4343
/*
4444
定义三个变量,它们分别初始化相应的值
@@ -47,7 +47,7 @@ Go语言里面定义变量有多种方式。
4747
*/
4848
vname1, vname2, vname3 := v1, v2, v3
4949

50-
现在是不是看上去非常的简单了`:=`这个符号直接取代了`var``type`,这样的代码是不是很简洁?这种形式叫做简短声明。不过它有一个限制,那就是它只能用在函数内部;在函数外部使用则会无法编译通过,比如说用它来定义全局变量
50+
现在是不是看上去非常简洁了`:=`这个符号直接取代了`var``type`,这种形式叫做简短声明。不过它有一个限制,那就是它只能用在函数内部;在函数外部使用则会无法编译通过,所以一般用`var`方式来定义全局变量
5151

5252
`_`(下划线)是个特殊的变量名,任何赋予它的值都会被丢弃。在这个例子中,我们将值`35`赋予`b`,并同时丢弃`34`
5353

@@ -63,29 +63,27 @@ Go对于已声明但未使用的变量会在编译阶段报错,比如下面的
6363

6464
## 常量
6565

66-
所谓常量,也就是在编译阶段就确定下来的值,而程序在运行时则无法改变该值。在Go程序中,常量可定义为数值、布尔值或字符串等类型。
66+
所谓常量,也就是在程序编译阶段就确定下来的值,而程序在运行时则无法改变该值。在Go程序中,常量可定义为数值、布尔值或字符串等类型。
6767

6868
它的语法如下:
6969

7070
const constantName = value
71+
//如果需要,也可以明确指定常量的类型:
72+
const Pi float32 = 3.1415926
7173

7274
下面是一些常量声明的例子:
7375

7476
const Pi = 3.1415926
7577
const i = 10000
7678
const MaxThread = 10
77-
const prefix = 'astaxie_'
78-
79-
当然如果需要,也可以明确指定常量的类型:
80-
81-
const Pi float32 = 3.1415926
79+
const prefix = "astaxie_"
8280

8381

8482
## 内置基础类型
8583

8684
### Boolean
8785

88-
在Go中,布尔值的类型为`bool`可用的值是`true``false`,默认为`false`
86+
在Go中,布尔值的类型为`bool`值是`true``false`,默认为`false`
8987

9088
//示例代码
9189
var isActive bool // 全局变量声明
@@ -99,30 +97,30 @@ Go对于已声明但未使用的变量会在编译阶段报错,比如下面的
9997

10098
### 数值类型
10199

102-
整数类型有无符号和带符号两种。Go同时支持`int``uint`,这两种类型的长度相同,但具体长度取决于编译器的实现。当前的gc和gccgo编译器在32位和64位平台上都使用32位来表示`int``uint`,但未来在64位平台上可能增加到64位。Go里面也有直接定义好位数的类型:`rune`, `int8`, `int16`, `int32`, `int64``byte`, `uint8`, `uint16`, `uint32`, `uint64``rune``int32`的别称,`byte``uint8`的别称。
100+
整数类型有无符号和带符号两种。Go同时支持`int``uint`,这两种类型的长度相同,但具体长度取决于不同编译器的实现。当前的gcc和gccgo编译器在32位和64位平台上都使用32位来表示`int``uint`,但未来在64位平台上可能增加到64位。Go里面也有直接定义好位数的类型:`rune`, `int8`, `int16`, `int32`, `int64``byte`, `uint8`, `uint16`, `uint32`, `uint64`其中`rune``int32`的别称,`byte``uint8`的别称。
103101

104102
>需要注意的一点是,这些类型的变量之间不允许互相赋值或操作,不然会在编译时引起编译器报错。
105103
>
106104
>如下的代码会产生错误
107105
>
108-
> var a int8
109-
> var b int32
110-
> c:=a + b
106+
>> var a int8
107+
>> var b int32
108+
>> c:=a + b
109+
>
111110
>另外,尽管int的长度是32 bit, 但int 与 int32并不可以互用。
112111
113112
浮点数的类型有`float32``float64`两种(没有`float`类型),默认是`float64`
114113

115-
这就是全部吗?No!Go还支持复数。它的默认类型是`complex128`(64位实数+64位虚数)。如果需要小一些的,也有`complex64`(32位实数+32位虚数)。复数的形式为`re + imi`,其中`re`是实数部分,`im`是虚数部分,而最后的`i`是虚数单位。下面是一个使用复数的例子:
114+
这就是全部吗?No!Go还支持复数。它的默认类型是`complex128`(64位实数+64位虚数)。如果需要小一些的,也有`complex64`(32位实数+32位虚数)。复数的形式为`RE + IMi`,其中`RE`是实数部分,`IM`是虚数部分,而最后的`i`是虚数单位。下面是一个使用复数的例子:
116115

117116
var c complex64 = 5+5i
118-
117+
//output: (5+5i)
119118
fmt.Printf("Value is: %v", c)
120119

121-
它会打印:(5+5i)
122120

123121
### 字符串
124122

125-
我们在上一节中讲过,Go中的字符串都是用`UTF-8`的形式编码的。字符串通过用一对双引号`""`)或反引号(`` ` ```` ` ``)括起来定义,它的类型是`string`
123+
我们在上一节中讲过,Go中的字符串都是采用`UTF-8`字符集编码。字符串是用一对双引号`""`)或反引号(`` ` `` `` ` ``)括起来定义,它的类型是`string`
126124

127125
//示例代码
128126
var frenchHello string // 声明变量为字符串的一般方法
@@ -148,7 +146,7 @@ Go对于已声明但未使用的变量会在编译阶段报错,比如下面的
148146
fmt.Printf("%s\n", s2)
149147

150148

151-
Go中可以使用`+`来链接两个字符串
149+
Go中可以使用`+`操作符来连接两个字符串
152150

153151
s := "hello,"
154152
m := " world"
@@ -157,7 +155,7 @@ Go中可以使用`+`来链接两个字符串:
157155

158156
修改字符串也可写为:
159157

160-
s := "hello"
158+
s := "hello"
161159
s = "c" + s[1:] // 字符串虽不能更改,但可进行切片操作
162160
fmt.Printf("%s\n", s)
163161

@@ -237,8 +235,8 @@ Go里面有一个关键字`iota`,这个关键字用来声明`enum`的时候采
237235

238236
### Go程序设计的一些规则
239237
Go之所以会那么简洁,是因为它有一些默认的行为:
240-
- 大写字母开头的变量是已导出的,也就是其它包可以读取的,类似`class``public`的概念;小写字母开头的就是未导出的
241-
- 大写字母开头的函数也是一样,相当于`public`的函数;小写字母开头的就是类似`private`
238+
- 大写字母开头的变量是可导出的,也就是其它包可以读取的,是公用变量;小写字母开头的就是不可导出的,是私有变量。
239+
- 大写字母开头的函数也是一样,相当于`class`中的带`public`关键词的公有函数;小写字母开头的就是有`private`关键词的私有函数。
242240

243241
## array、slice、map
244242

@@ -252,7 +250,8 @@ Go之所以会那么简洁,是因为它有一些默认的行为:
252250
var arr [10]int // 声明了一个int类型的数组
253251
arr[0] = 42 // 数组下标是从0开始的
254252
arr[1] = 13 // 赋值操作
255-
fmt.Printf("The first element is %d\n", arr[0]) // 获取数据
253+
fmt.Printf("The first element is %d\n", arr[0]) // 获取数据,返回42
254+
fmt.Printf("The last element is %d\n", arr[9]) //返回未赋值的最后一个元素,默认返回0
256255

257256
由于长度也是数组类型的一部分,因此`[3]int``[4]int`是不同的类型,数组也就不能改变长度。数组之间的赋值是值的赋值,即当把一个数组作为参数传入函数的时候,传入的其实是该数组的副本,而不是它的指针。如果要使用指针,那么就需要用到后面介绍的`slice`类型了。
258257

@@ -264,7 +263,7 @@ Go之所以会那么简洁,是因为它有一些默认的行为:
264263

265264
c := [...]int{4, 5, 6} // 可以省略长度而采用`...`的方式,Go会自动根据元素个数来计算长度
266265

267-
也许你会说,我想数组里面还是数组,能实现吗?当然咯,Go支持嵌套数组,即多维数组。比如下面的代码就声明了一个二维数组:
266+
也许你会说,我想数组里面的值还是数组,能实现吗?当然咯,Go支持嵌套数组,即多维数组。比如下面的代码就声明了一个二维数组:
268267

269268
// 声明了一个二维数组,该数组以两个数组作为元素,其中每个数组中又有4个int类型的元素
270269
doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}
@@ -279,9 +278,9 @@ Go之所以会那么简洁,是因为它有一些默认的行为:
279278

280279
### slice
281280

282-
在很多应用场景中,数组并不能满足我们的需求。在刚开始时,我们并不知道需要多大的数组,因此我们就需要“动态数组”。在Go里面这种数据结构叫`slice`
281+
在很多应用场景中,数组并不能满足我们的需求。在初始定义数组时,我们并不知道需要多大的数组,因此我们就需要“动态数组”。在Go里面这种数据结构叫`slice`
283282

284-
`slice`并不是真正意义上的动态数组,而是一个引用类型。`slice`总是指向底层的一个`array``slice`的声明也可以像`array`一样,只是不需要长度。
283+
`slice`并不是真正意义上的动态数组,而是一个引用类型。`slice`总是指向一个底层`array``slice`的声明也可以像`array`一样,只是不需要长度。
285284

286285
// 和声明array一样,只是少了长度
287286
var fslice []int
@@ -306,7 +305,7 @@ Go之所以会那么简洁,是因为它有一些默认的行为:
306305
b = ar[3:5]
307306
// b的元素是:ar[3]和ar[4]
308307

309-
>注意`slice`和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用`...`自动计算长度,而声明``slice``时,方括号内没有任何字符。
308+
>注意`slice`和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用`...`自动计算长度,而声明`slice`时,方括号内没有任何字符。
310309
311310
它们的数据结构如下所示
312311

@@ -316,7 +315,7 @@ slice有一些简便的操作
316315

317316
- `slice`的默认开始位置是0,`ar[:n]`等价于`ar[0:n]`
318317
- `slice`的第二个序列默认是数组的长度,`ar[n:]`等价于`ar[n:len(ar)]`
319-
- `slice`如果从一个数组里面直接获取,可以这样`ar[:]`,因为默认第一个序列是0,第二个是数组的长度,即等价于`ar[0:len(ar)]`
318+
- 如果从一个数组里面直接获取`slice`,可以这样`ar[:]`,因为默认第一个序列是0,第二个是数组的长度,即等价于`ar[0:len(ar)]`
320319

321320
下面这个例子展示了更多关于`slice`的操作:
322321

@@ -376,8 +375,7 @@ slice有一些简便的操作
376375
numbers["three"] = 3
377376

378377
fmt.Println("第三个数字是: ", numbers["three"]) // 读取数据
379-
// 打印出来如下:
380-
// 第三个数字是: 3
378+
// 打印出来如:第三个数字是: 3
381379

382380
这个`map`就像我们平常看到的表格一样,左边列是`key`,右边列是值
383381

@@ -416,15 +414,19 @@ slice有一些简便的操作
416414

417415
`make`用于内建类型(`map``slice``channel`)的内存分配。`new`用于各种类型的内存分配。
418416

419-
内建函数`new`本质上说跟其它语言中的同名函数功能一样:`new(T)`分配了零值填充的`T`类型的内存空间,并且返回其地址,即一个`*T`类型的值。用Go的术语说,它返回了一个指针,指向新分配的类型`T`的零值。有一点非常重要:`new`返回指针。
417+
内建函数`new`本质上说跟其它语言中的同名函数功能一样:`new(T)`分配了零值填充的`T`类型的内存空间,并且返回其地址,即一个`*T`类型的值。用Go的术语说,它返回了一个指针,指向新分配的类型`T`的零值。有一点非常重要:
418+
419+
>`new`返回指针。
420+
421+
内建函数`make(T, args)``new(T)`有着不同的功能,make只能创建`slice``map``channel`,并且返回一个有初始值(非零)的`T`类型,而不是`*T`。本质来讲,导致这三个类型有所不同的原因是指向数据结构的引用在使用前必须被初始化。例如,一个`slice`,是一个包含指向数据(内部`array`)的指针、长度和容量的三项描述符;在这些项目被初始化之前,`slice``nil`。对于`slice``map``channel`来说,`make`初始化了内部的数据结构,填充适当的值。
420422

421-
内建函数`make(T, args)``new(T)`有着不同的功能,它只能创建`slice``map``channel`,并且返回一个有初始值(非零)的`T`类型,而不是`*T`。本质来讲,导致这三个类型有所不同的原因是指向数据结构的引用在使用前必须被初始化。例如,一个`slice`,是一个包含指向数据(内部`array`)的指针、长度和容量的三项描述符;在这些项目被初始化之前,`slice``nil`。对于`slice``map``channel`来说,`make`初始化了内部的数据结构,填充适当的值。`make`返回初始化后的(非零)值。
423+
>`make`返回初始化后的(非零)值。
422424
423425
下面这个图详细的解释了`new``make`之间的区别。
424426

425427
![](images/2.2.makenew.png?raw=true)
426428

427-
关于“零值”,所指并非是空值,而是一种“变量未填充前”的默认值。通常为 0
429+
关于“零值”,所指并非是空值,而是一种“变量未填充前”的默认值,通常为0
428430
此处罗列 部分类型 的 “零值”
429431

430432
int 0

0 commit comments

Comments
 (0)