# Effective Go-2
Date: 2021-04-07


#### **分号**

若在一行最后一个标识符为以下类型

- 数字
- 字符串常量
- 特殊标识符号；break continue fallthrough return ++ -- ) }

词法分析器会在标识符后添加分号， 与C不同GO很多地方都省略分号。

另在在if for switch select控制结构后要接 “{”, 例如：

```
if i < f() {
    g()
}
```

而不要写成

```
if i < f() 
{
    g()
}
```

 

#### **控制结构**

if/switch/for

- If switch语句中可以接受初始化语句

```
if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}
```

- For 遍历数组，切片，字符串或者map时，可以使用range子句

```
for key, value := range oldMap {
    newMap[key] = value
}

```

- Switch中有两个比较特殊的地方，

break跳出指定一个标签范围：

```
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)
        }
    }
```

与C不同他不仅支持整数，枚举还支持类型判断

```
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
}
```

- 其他

if语句中支持初始化语句

```
if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}
```

平行赋值，可以实现变量交换。

```
a := 1
b := 2
a, b = b, a
```

a = 2, b = 1

++，--认为是一个语句, 不是一个操作符，单启一行。

```
a := 1
a++
b := 2
b++
a, b = b, a
```

a = 3, b = 2

 

#### **函数**

函数主要是两个特征

- 多返回值

```
func returnMulitValues() (int, int) {
    return rand.Intn(10), rand.Intn(100)
}

func TestFn(t *testing.T) {
    a, b := returnMulitValues()
    t.Log(a, b)
}
```

- defer 有些类似C++中的析构函数，可以利用他的特性释放资源。防止遗漏。

```
func TestDefer(t *testing.T) {
    defer func() {
        t.Log("Clear resources")
    }()
    t.Log("Started")
    panic("Fatal error")
}
```

- 其他

可以给返回值命名

```
func nextInt(b []byte, pos int) (value, nextPos int) {
```

 

#### **参考及引用**

Photo by **[Lachlan Ross](https://www.pexels.com/@lachlan-ross?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)** from **[Pexels](https://www.pexels.com/photo/rocky-seashore-with-calm-seawater-at-twilight-6510271/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)**

https://golang.org/doc/effective\_go

