预备知识

Go支持两种类型的注释,这跟C++是一样的。行注释(//) 以及多行注释 / and end with /.

Go标识符由数字和字母组成,第一个字符只能字母, 同时标识符不能为关皱字,比如if,for. 开头的字母可以为下划线_, 以及任何Unicoede字符 "中"。 编译器会阻止你使用以下的关键字作为标识符

Table 2.1 Go's Keyworkds

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

Go也有很多预定义标识符;

Table 2.2 Go's Predefined Identifiers

append copy int8 nil true
bool delete int16 panic unit
byte error int 32 print unit8
cap false int64 println uint16
close float32 iota real unit32
complex float64 len recover unit64
complex64 imag make rune unitptr
complex12 int new string

标识符是区分大小写的,比如LINECOUNT, Linecount, LineCount, lineCount, linecount是5个不同的标识符。 如果第一个字母为大写,则被认为它的public, 其它的则认为是private. (这条规则不适用于package names. 通常包的名字全部都是小写的).

空白标识符(_), 它是一个占位符

count, err = fmt.Println(x)
// get number of bytes printed and error
count, _ = fmt.Println(x)   
// get number of bytes printed; discard error
_, err = fmt.Println(x)     
// discard number of bytes printed; get error
fmt.Println(x)
// ignore return values

常量与变量

常量通过关键字const来声明。 变量通过var声明, 或者使用短变量声明语法。Go支持类型推断。 以下是一些例子:

const limit = 512        //constant; limit的类型可以为任何的数字
const top unit16 = 1421  //constant; 类型为unit16
start := -19             //variable; 推断出的类型为 int
end := int64(987653210)  //variable; type: int64
var i int                //variable; value 0; type: int
var debug = false        //variable; inferred type: bool
checkResults := true     //variable; inferred type: bool
stepSize := 1.5          //variable; inferred type: float:64
acronym := "FOSS"         //variable; infferred type: string

对于数字字面量, Go的推断类型为int, 浮点型的则为float64. complex则为 complex128; 正常的原则是我们不指定类型,除非我们不需要Go推断,我们才需要指定具体的类型。 未指定数字类型的常量,可以表示任意的内置数据类型(e.g., limit 可以表示integers 或者浮点数).

变量 i 没有给定明确的值。 但Go会为没有给定值的类型分配此类型的零值(numeric 0, string 为‘’.

#### 枚举

在声明多个constants时,我们可以不用多次的使用const, 而是只需要使用一次const. 如下所示

const Cyan = 0        | const(               | const (
const Magenta = 1     |    Cyan = 0          |    Cyan = iota //0
const Yellow = 2      |    Magenta = 1       |    Magenta     //1
                      |    Yellow = 2        |    Yellow      //2
                      | )                    | )

上面三段代码都的效果都是一样的, 在第三段中,除非明确的指定了Cyan的值,否则分配一个0。 第二个以及后续的变量在此基础上加1

预定义标识符iota表示连续的整型常量。 每一个const group中,都会重置iota的值为0.

另一方面, 如果第三段代码段不是iota , Cyan 则为 0, Magenta的值则被设置为Cyan的值, 而Yellow 的值则设置为 Magenta的值。 所以它们的值都为0. 相似的, 如果Cyan设置为9, 则所有的都为9。 或者如果Magenta设置为5, 而Cyan没有明确的指定值或者iota, 则Cyan为0, Yellow 则为5.

type BitFlag int
const(
    Active  BitFlag = 1 << iota // 1 << 0 == 1
    Send    // Implicitly BitFlag = 1 << iota   // 1 << 1 == 2
    Receive // Implicitly BitFlag = 1 << iota   // 1 << 2 == 4
)
flag := Active | Send

在这段代码里, 我们创建了三个位标志, 然后设置了变量flag的值为3。

BitFlay类已经可以正常使用, 但它对于调式信息却还不是很方便, 如果我们想要打印flag变量,我们只能得到一个3, 而没有更多的指示信息。在Go编程中可以很容易的控制自定义类型的输出。因为fmt包是调用自定义类型的 String方法。所以为了使用BigFlag类型可以打印更多的信息,我们可以添加一个合适的String()方法。

func (flag BitFlag) String() string {

    var flags []string

    if flag&Active == Active {
        flags = append(flags, "Active")
    }
    if flag&Send == Send {
        flags = append(flags, "Send")

    }
    if flag&Receive == Receive {
        flags = append(flags, "Receive")
    }

    if len(flags) > 0 {
        return fmt.Sprintf("%d(%s)", int(flag), strings.Join(flags, "| "))
    }

    return "0()"
}
fmt.Println(BitFlag(0), Active, Send, Receive, Active|Receive)
//0() 1(Active) 2(Send) 4(Receive) 5(Active| Receive)