Go 约定俗成

141 阅读2分钟

名字

包名 package name

1,小写,单字(single-word) 2,包名就是源代码所在的目录的基础名

Getter/Setter方法

如果有一个字段叫owner Owner // get方法 SetOwner // set方法

owner := obj.Owner()
if owner != user {
    obj.SetOwner(user)
}

接口名

单方法的接口名,就是方法名+er,如

type Reader interface {
   Read(p []byte) (n int, err error)
}

转化成字符串的方法是String,而不是ToString

分号 semecolons

Go用分号来结束语句(statement),但是分号不用出现在源代码中,词法分析器使用简单的规则自动插入分号。 规则是 一行的最后一个字符是 ,identifier,字面值或 下列字符之一,则会插入一个分号。

break continue fallthrough return ++ -- ) }

总结为:如果换行出现在可以结束一条语句的符号之后,则插入一个分号

控制结构

if

if和switch接受一个初始化语句,可定义一个本地变量。

go中不多用else,而是直接在if中结束掉,错误直接return

再次声明,重新赋值

f, err := os.Open(name)
if err != nil {
    return err
}
d, err := f.Stat()

err在第二次出现时,是重新赋值。

:= 可以在以下情况再次出现

1 在同一个scope

for

有三种形式

// Like a C for
for init; condition; post { }

// Like a C while
for condition { }

// Like a C for(;;)
for { }

短声明 易于创建一个 循环内使用的index

sum := 0
for i := 0; i < 10; i++ {
    sum += i
}

If you're looping over an array, slice, string, or map, or reading from a channel, a range clause can manage the loop.

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

If you only need the first item in the range (the key or index), drop the second:

for key := range m {
    if key.expired() {
        delete(m, key)
    }
}

If you only need the second item in the range (the value), use the blank identifier, an underscore, to discard the first:

sum := 0
for _, value := range array {
    sum += value
}

并行赋值 parallel assignment

stackoverflow.com/questions/4…

The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.

并行赋值分两阶段,第一阶段,确定左边的位置和右边的值,第二阶段,进行从左到右的赋值。

switch

如果switch没有表达式,等同于 switch true, 可以当作if else 链来用。

没有自动的 fall through,但case中可以放多个,用逗号分隔

func shouldEscape(c byte) bool {
    switch c {
    case ' ', '?', '&', '=', '#', '+', '%':
        return true
    }
    return false
}

下面这个例子展示的是break,如果break后面没有label,只是break掉switch,for循环还是继续的, 需要想要break掉for循环, 使用label,而且label只在循环中使用。label和for之间,不能有其他代码。

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是关键字

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
}