Go的基本语法


变量

变量声明

Go语言的变量声明方式与C和C++语言有明显的不同。对于纯粹的变量声明,Go语言引入了关键字var,而类型信息放在变量名之后,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var v1 int
var v2 string
var v3 [10]int // 数组
var v4 []int // 数组切片
var v5 struct {
f int
}
var v6 *int // 指针
var v7 map[string]int // map,key为string类型,value为int类型
var v8 func(a int) int
var (
v1 int
v2 string
)

变量声明语句不需要使用分号作为结束符。与C语言相比,Go语言摒弃了语句必须以分号作为语句结束标记的习惯。

变量初始化

对于声明变量时需要进行初始化的场景,var关键字可以保留,但不再是必要的元素,如下:

1
2
3
var v1 int = 10 // 正确的使用方式1
var v2 = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型
v3 := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型

出现在:=左侧的变量不应该是已经被声明过的,否则会导致编译错误。

变量赋值

传统赋值,如下:

1
2
var v10 int
v10 = 123

另外,还有多重赋值功能,如下为交换i和j的值:

1
i, j = j, i

匿名变量

对函数

1
2
3
func GetName() (firstName, lastName, nickName string) {
return "May", "Chan", "Chibi Maruko"
}

若只想获得nickName,则函数调用语句可以用如下方式编写:

1
_, _, nickName := GetName()

常量


在Go语言中,常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。

字面常量

所谓字面常量(literal),是指程序中硬编码的常量,如:

1
2
3
4
5
-12
3.14159265358979323846 // 浮点类型的常量
3.2+12i // 复数类型的常量
true // 布尔类型的常量
"foo" // 字符串常量

常量定义

通过const关键字,你可以给字面常量指定一个友好的名字:

1
2
3
4
5
6
7
8
9
const Pi float64 = 3.14159265358979323846
const zero = 0.0 // 无类型浮点常量
const (
size int64 = 1024
eof = -1 // 无类型整型常量
)
const u, v float32 = 0, 3 // u = 0.0, v = 3.0,常量的多重赋值
const a, b, c = 3, 4, "foo" //a=3,b=4,c="foo", 无类型整型和字符串常量
const mask = 1 << 3 //常量定义的右值也可以是一个在编译期运算的常量表达式,比如

但是比如const Home = os.GetEnv("HOME")就是错误的,因为函数os.GetEnv()只有在运行期才能知道返回结果,在编译期并不能确定,所以无法作为常量定义的右值。

预定义常量

Go语言预定义了这些常量:true、false和iota。

iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1。例

1
2
3
4
5
6
7
8
9
10
11
12
13
const (				// iota被重设为0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const x = iota // x == 0 (因为iota又被重设为0了)
const y = iota // y == 0 (同上)
// 也可以下面这样简单使用
const ( // iota被重设为0
c0 = iota // c0 == 0
c1 // c1 == 1
c2 // c2 == 2
)

iota在每个const开头被重设为0。

枚举

Go语言并不支持众多其他语言明确支持的enum关键字,使用const来实现这个功能。

1
2
3
4
5
6
7
8
9
10
const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
numberOfDays // 这个常量没有导出
)

同Go语言的其他符号(symbol)一样,以大写字母开头的常量在包外可见,小写字母为不可见。上面例子中numberOfDays为包内私有,其他符号则可被其他包访问。

类型

Go语言内置以下这些基础类型:

  • 布尔类型:bool。
  • 整型:int8、byte、int16、int、uint、uintptr等。
  • 浮点类型:float32、float64。
  • 复数类型:complex64、complex128。
  • 字符串:string。
  • 字符类型:rune。
  • 错误类型:error。

此外,Go语言也支持以下这些复合类型:

  • 指针(pointer)
  • 数组(array)
  • 切片(slice)
  • 字典(map)
  • 通道(chan)
  • 结构体(struct)
  • 接口(interface)

布尔类型

1
2
3
var v1 bool
v1 = true
v2 := (1 == 2) // v2也会被推导为bool类型

给布尔类型变量赋值int,如上例子中v1 = 1则会编译报错。

整形

要注意的几点:

  • int和int32在Go语言里被认为是两种不同的类型,编译器也不会帮你自动做类型转换。
  • Go语言支持下面的常规整数运算:+、-、*、/和%,和C语言一致。
  • Go语言支持以下的几种比较运算符:>、<、==、>=、<=和!=,和C语言一致。
  • Go语言的大多数位运算符与C语言都比较类似,除了取反在C语言中是~x,而在Go语言中 是^x。

浮点型

浮点型用于表示包含小数点的数据,比如1.234就是一个浮点型数据。Go语言中的浮点类型采用IEEE-754标准的表达方式。

Go语言定义了两个类型float32和float64,其中float32等价于C语言的float类型,float64等价于C语言的double类型。定义一个浮点型。

1
fvalue2 := 12.0 // 如果不加小数点,fvalue2会被推导为整型而不是浮点型

因为浮点数不是一种精确的表达方式,所以像整型那样直接用==来判断两个浮点数是否相等是不可行的,这可能会导致不稳定的结果。下面是一种推荐的替代方案:

1
2
3
4
5
import "math"
// p为用户自定义的比较精度,比如0.00001
func IsEqual(f1, f2, p float64) bool {
return math.Fdim(f1, f2) < p
}

复数类型

复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部(real),一个表示虚部(imag)。例如

1
2
3
4
var value1 complex64			// 由2个float32构成的复数类型
value1 = 3.2 + 12i
value2 := 3.2 + 12i // value2是complex128类型
value3 := complex(3.2, 12) // value3结果同 value2

字符串

字符串声明非常简单

1
2
3
4
5
6
7
8
var str string //声明一个字符串变量
str = "Hello world" //字符串赋值
ch := str[0] // 取字符串第一个字符
fmt.Printf("The length of \"%s\" is %d \n", str, len(str))
fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)
//------分割线----------
str := "Hello world" //字符串也可以在声明时进行初始化
str[0] = 'X'//错误,在已经初始化的字符串里就不能使用数组方式修改值了

字符串常用的操作,连接 x+y

参考链接


1.Go语言编程
2.Go编程语言