Contents
  1. 1. Getters and Setters
  2. 2. 分号
  3. 3. 短声明
  4. 4. 多重赋值
  5. 5. switch中合并多个case
  6. 6. 带标签的break
  7. 7. Type switch
  8. 8. new和make
  9. 9. slice
  10. 10. init函数
  11. 11. 方法:Pointers vs. Values
  12. 12. for range中的变量
  13. 13. 并发与并行
  14. 14. panic && recover

Getters and Setters

Go也可以创建Getters and Setters,而且它们并不需要以get或set开头。

分号

Go大部分的;可以省略,是因为它的语法分析器会自动为你加上。

短声明

1
2
f, err := os.Open(name)
d, err := f.Stat()

在第二个语句中,d是新建变量,而err是重新赋值。

多重赋值

Go中没有逗号运算符,++--是声明而非语句,但你可以用并列多重赋值来在for循环中操作多个变量

1
2
3
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}

switch中合并多个case

使用逗号隔开即可

1
2
3
4
5
6
7
func shouldEscape(c byte) bool {
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
return true
}
return false
}

带标签的break

可以break指定的loop,即先为循环设置label,再break label。注意第二个case中的(break Loop),多重嵌套中会很顺手。同时注意这里使用到了不跟表达式的switch.

同样的,continue也可跟标签,但只限于循环中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Loop:
for n := 0; n < len(src); n += size {
switch {
case src[n] < sizeOne:
if validateOnly {
break
}
size = 1
update(src[n])
case src[n] < sizeTwo:
if n+1 >= len(src) {
err = errShortInput
break Loop
}
if validateOnly {
break
}
size = 2
update(src[n] + src[n+1]<<shift)
}
}

Type switch

用于动态地发现接口变量类型,使用类型断言并在括号中传入 type

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}

new和make

Go有两个基本分配操作,new和make,new为变量分配内存并置零(不同于其它语言的初始化)。

make则为slice , map和chan专用的,它不返回零值变量,而是初始化。

slice

slice其实是对array进行了再包装(pointer, length, and capacity),它类似指针传递,但需要注意类似append这样的操作返回的是新的slice。

不同于C的是,array也是值传递的,也就是说会产生一个新的数组Copy。

init函数

每个源文件都可以有init方法,它在所有变量初始化之后执行。它可以用来实现无法在声明中完成的初始化,确认和修复初始执行环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
func init() {
if user == "" {
log.Fatal("$USER not set")
}
if home == "" {
home = "/home/" + user
}
if gopath == "" {
gopath = home + "/go"
}
// gopath may be overridden by --gopath flag on command line.
flag.StringVar(&gopath, "gopath", gopath, "override default GOPATH")
}

方法:Pointers vs. Values

receiver为值的方法可被值和指针调用,而指针receiver的方法只能被指针调用。

for range中的变量

for i:=range varaible中,变量i会在每一轮循环中重复使用,如果直接在匿名函数中使用i,将易产生问题,这里有个种方式可行。一、使用带参数的匿名函数将i作为参数传递;二、在循环体开始处使用新变量保存i值,如i:=i,这是合法的。

并发与并行

Go是并发语言而非并行语言,所谓并发:程序由多个独立执行组件组成;而并行:在多个CPU上平行运算以提高效率

panic && recover

panic函数会立即停止当前函数执行,并回溯gorouting的调用栈,执行之前defer方法,如果回溯到顶层,那么程序就退出了。
内建的recover()函数可以中止这个回溯过程并将最初传递给panic的参数以error的形式返回。
注意,recover只能在defer中使用,否则返回nil.

Contents
  1. 1. Getters and Setters
  2. 2. 分号
  3. 3. 短声明
  4. 4. 多重赋值
  5. 5. switch中合并多个case
  6. 6. 带标签的break
  7. 7. Type switch
  8. 8. new和make
  9. 9. slice
  10. 10. init函数
  11. 11. 方法:Pointers vs. Values
  12. 12. for range中的变量
  13. 13. 并发与并行
  14. 14. panic && recover