变量、类型和关键字

Go 在语法上有着类 C 的感觉。如果你希望将两个(或更多)语句放在一行书写,它们必须用分号 (’;’) 分隔。一般情况下,你不需要分号。

Go 同其他语言不同的地方在于变量的类型在变量名的后面。

不是:int a,而是 a int。

当定义了一个变量,它默认赋值为其类型的 null 值。

在 var a int后,a 的 值为 0。而 var s string,意味着 s 被赋值为零长度字符串,也就是 “”。

在Go中,声明和赋值是两过程,但是可以连在一起。比较下面作用相同的代码片段。

用 = 声明

1
2
3
4
5
6
7
var a int
var b bool
a = 15
b = false

用:= 声明

1
2
3
a := 15
b := false

在左边使用了关键字 var 声明变量,然后赋值给它。右边的代码使用了 := 使得在一 步内完成了声明和赋值(这一形式只可用在函数内)。在这种情况下,变量的类型是由值推演出来的。值15表示是int 类型,值false告诉Go 它的类型应当是bool。多个var 声明可以成组;const 和import 同样允许这么做。留意圆括号的使用:

1
2
3
4
5
6
7
var  (
x int
b bool
)

有相同类型的多个变量同样可以在一行内完成声明:var x, y int让x和y都是int类型变量。同样可以使用 平行赋值:

1
a, b := 20, 16

让a和b都是整数变量,并且赋值 20 给 a,16 给 b。

一个特殊的变量名是_(下划线)。任何赋给它的值都被丢弃。在这个例子中,将35赋值给b,同时丢弃34。

1
_, b := 34, 35

Go 的编译器对声明却未使用的变量在报错。下面的代码会产生这个错误:声明了i却未使用

1
2
3
4
5
6
7
package   main
func  main() {
var  i int
}

布尔类型

布尔类型表示由预定义的常量 true 和 false 代表的布尔判定值。布尔类型是 bool。


数字类型

Go有众所周知的类型如int,这个类型根据你的硬件决定适当的长度。意味着在32位硬件上,是32位的;在64位硬件上是64位的。

注意:int是32或64位之一,不会定义成其他值。uint情况相同。

如果你希望明确其长度,你可以使用int32或者uint32。完整的整数类型列表(符号和无符号)是 int8,int16,int32,int64 和 byte,uint8,uint16,uint32, uint64。byte 是 uint8 的别名。浮点类型的值有 float32 和 float64 (没有 float 类 型)。64 位的整数和浮点数总是 64 位的,即便是在 32 位的架构上。

需要留意的是这些类型全部都是独立的,并且混合用这些类型向变量赋值会引起编译 器错误,例如下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
func main()      {
var a int           // 通用整数类型
var b int32      // 32 位整数类型
a = 15
b = a+ a           // 混合这些类型是非法的
b = b+ 5           //5 是一个(未定义类型的)常量,所以这没%问题
}

在b=a+a触发一个赋值错误:

types.go:7: cannot use a + a (type int) as type int32 in assignment

赋值可以用八进制、十六进制或科学计数法:077,0xFF,1e3 或者 6.022e23 这些都是合法的。


常量

常量在Go中,也就是 constant。它们在编译时被创建,只能是数字、字符串或布尔值;const x = 42 生成x这个常量。可以使用iota生成枚举值。

1
2
3
4
5
6
7
const  (
a = iota
b = iota
)

第一个iota 表示为 0,因此a等于0,当iota 再次在新的一行使用时,它的值增加了1,因此b的值是1。

也可以像下面这样,省略Go重复的= iota:

1
2
3
4
5
6
7
const  (
a = iota
b                 // Implicitly b = iota
)

如果需要,可以明确指定常量的类型:

1
2
3
4
5
6
7
const  (
a = 0                      // Is an int now
b string  = "0"
)

字符串

另一个重要的内建类型是string。赋值字符串的例子:

s := “Hello World !”
字符串在Go中是UTF-8的由双引号(”)包裹的字符序列。如果你使用单引号(’)则 表示一个字符(UTF-8 编码)——这种在Go中不是string。

一旦给变量赋值,字符串就不能修改了:在** Go **中字符串是不可变的。从C来的用户, 下面的情况在Go中是非法的。

`var s string = “hello”

s[0] = ‘c’ //修改第一个字符为’c’,这会报错`

在 Go 中实现这个,需要下面的方法:

`s := “hello”

c := []rune(s)

c[0] = ‘c’

s2 := string(c)

fmt.Printf(“%s\n”, s2)`

2转换 s 为 rune 数组;

3修改数组的第一个元素;

4 创建新的字符串 s2 保存修改;

5 用 fmt.Printf 函数输出字符串。

多行字符串

基于分号的置入,你需要小心使用多行字符串。如果这样写:

`s := “Starting part”

  • “Ending part”`

会被转换为:

`s := “Starting part” ;

  • “Ending part” ;`

这是错误的语法,应当这样写:

s := "Starting part" + "Ending part"

Go就不会在错误的地方插入分号。另一种方式是使用反引号 ` 作为原始字符串符号:

s :=Starting part Ending part``

留意最后一个例子s现在也包含换行。不像转义字符串标识 ,原始字符串标识的值 在引号内的字符是不转义的。


 

rune

Rune是int32的别名。用UTF-8进行编码。这个类型在什么时候使用呢?例如需要遍 历字符串中的字符。可以循环每个字节(仅在使用 US ASCII 编码字符串时与字符等价, 而它们在 Go 中不存在!)。因此为了获得实际的字符,需要使用 rune 类型。

 


 

复数

Go原生支持复数。它的变量类型是complex128(64位虚数部分)。如果需要小一些的,还有complex64–32位的虚数部分。

复数写为 re + imi,re是实数部分,im是虚数部分,而i是标记 ’i’ (√−1)。使用复数的一个例子:

var c complex64 = 5+5i;fmt.Printf("Value is: %v", c)

将会打印:(5+5i)

 


 

错误

任何足够大的程序或多或少都会需要使用到错误报告。因此Go有为了错误而存在的内建类型,叫做 error。

var e error 定义了一个error类型的变量e,其的值是nil。这个error 类型是一个接口。