基础语法

// fileName: simple.go

package main

import (

"fmt"

"sync"

)

func input(ch chan string) {

defer wg.Done()

defer close(ch)

var input string

fmt.Println("Enter 'EOF' to shut down: ")

for {

_, err := fmt.Scanf("%s", &input)

if err != nil{

fmt.Println("Read input err: ", err.Error())

break

}

if input == "EOF"{

fmt.Println("Bye!")

break

}

ch <- input

}

}

func output(ch chan string) {

defer wg.Done()

for value := range ch{

fmt.Println("Your input: ", value)

}

}

var wg sync.WaitGroup

func main() {

ch := make(chan string)

wg.Add(2)

go input(ch) // 读取输入

go output(ch) // 输出到命令行

wg.Wait()

fmt.Println("Exit!")

}

从命令行接受用户的输入并输出到命令行中,可在文件所在命令行下执行 go run simple.go 启动程序。代码中使用 go 关键字启动了两个协程分别处理读取输入和输出到命令行,协程为 Go 中执行代码片段的用户级轻量线程,协程之间通过 chan 进行数据传输,chan 中的数据传输遵循先进先出的顺序,并保证每次只能有一个协程发送或者接收数据。
每一个 Go 文件都需要在文件开头标注所属的包,Go 程序是由包组成的,上述代码中的 Go 文件位于 main 包下。Go 中规定可执行程序必须具备 main 包,并且在 main 包下具备可执行的 main 函数。通过 import 关键字就可以导入其他包中的代码进行使用。
从上述代码中我们可以了解到 Go 的部分语法特点:

- 变量声明时,变量类型位于变量名后;

- 对于 if 和 for 等语句的子句条件,无须使用 “()” 包起来;

- 语句结束无须使用“;”之类的分隔符,通过换行区分;

- “{” 必须紧跟在对应语句的后面,不可另起一行。

为了使 Go 程序运行起来,接下来我们就介绍一些简单的 Go 编译工具和命令。
第一个,go run 命令。该命令将直接编译和执行源码中的 main 函数,你可以在命令后添加参数,这部分参数会作为代码可以接受的命令行输入提供给程序。以上面的 simple.go 小程序为例子,进入到 simple.go 文件的目录下,执行如下命令即可运行 simple.go 小程序:

go run simple.go

第二个,go build 命令。该命令通过 Go 的并发特性对代码进行函数粒度的并发编译,它会将源码编译为可执行文件,默认将编译该目录下的所有源码。也可以在命令后添加多个文件名,go build 将编译这些源码,输出可执行文件。
比如,进入到我们上面 simple.go 文件的目录下,执行如下命令:

go build -o simple // -o 用于指定生成可执行文件名称

// 或者
go build simple.go

都将在当前目录下生成一个 simple 的可执行文件,可双击直接运行。
接下来我们就详细讲解一下 Go 语言中的函数声明、变量的声明与初始化、指针、struct 等基础语法。

函数声明

func funcName(params)(return params){

function body

}

在同一个包内,函数名不可重名。如果函数希望能在包外被访问,则需要将函数名的首字母大写,表示该函数是包外公开的。
函数可以接受 0 个或者以上参数,在声明参数列表时,需要注意参数名在前、类型在后。对于连续类型相同的多个参数,可以省略参数类型,在最后一个参数中保留类型即可。Go 的函数支持多返回值和命名返回值,但是命名返回值和非命名返回值不能混合使用。一个综合的函数声明示例如下:

func Div(dividend, divisor int)(quotient, remainder int) {

quotient = dividend/divisor

remainder = dividend%divisor

return

}

上述代码中声明了一个包外公开的 Div 函数,接受 dividend、divisor 两个参数,并返回quotient、remainder 两个命名返回值,它们可以在函数体中被直接赋值使用。这里需要注意的是,在使用命名返回值时,我们需要在函数结束时显式使用 return 语句进行返回。

变量的声明与初始化

Go 中使用关键字 var 声明变量,变量名在前,类型在最后,声明形式如下:

var name T

在 Go 中,声明的变量都必须被使用,否则会编译失败。变量声明之后,会被默认初始化为初值。当然,我们也可以在声明时直接进行初始化,使用赋值符号 “=”,形式如下:

var name T = expression

Go 中支持类型推荐,在变量声明和初始化可以省略类型,由编译器根据 “=” 右边的表达式推导变量的类型。

var a = 100

a 中的类型会被编译器推导为 int。Go 中还支持短变量声明和初始化,形式更加精简:

name := expression

该种形式需要 “:=” 的左值存在没有定义过的变量,且无法在函数外使用。短变量形式支持多个变量的声明和初始化,如:

value, _ := fmt.Println()

在多个短变量的声明和初始化中,需要保证左值最少有一个新变量,否则编译会失败。对于不需要使用的变量,可以使用匿名变量 “” 来处理,如上述例子中使用 “” 来接受函数调用返回的 error,表示赋予该标识符的值将被直接舍弃,无法在后续代码中使用。匿名变量可以在代码中多次声明使用。