Go语言入门系列(二)之基础语法总结   1. 认识HelloWorld 2. 变量 3. 数据类型 4. 常量 5. 初识函数 6. 导出名 7. 流程控制语句

Go语言入门系列(二)之基础语法总结
 
1. 认识HelloWorld
2. 变量
3. 数据类型
4. 常量
5. 初识函数
6. 导出名
7. 流程控制语句

 

1. 认识HelloWorld

在前面的《Go语言入门系列(一)之Go的安装和使用》这篇文章中已经写过HelloWorld.go了,现在就来逐行认识一下它。

package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}

第1行:我们的Go程序是由——package构成的,包的声明形式为:package <包名>。该行的意思是:当前HelloWorld.go文件属于main包。

第2行:如果你使用过Java或Python,那你对import肯定不陌生。该行的意思是:导入一个名为fmt的包。如果需要导入多个包,有两种写法:

import "fmt"
import "math"

或者使用分组形式同时导入多个包

import (
	"fmt"
	"math/rand"
)

显然第二种使用括号,以分组的形式导入更加方便。

第3行:我们使用func关键字来声明一个函数,在这个例子中,我们声明的是main函数。如果你有过其他语言的编程经验,肯定熟悉main函数的作用:程序的入口。

第4行:我们的函数内容放在函数的{}中,在该例中,调用了fmt包中的打印方法,由此可见,Golang语言调用函数的方法和Java、Python一样使用小数点:<包名>.<函数名>

看完这几行简单代码,我们发现:在Go语言中,并不需要分号;来结束语句。

2. 变量

2.1. 命名规范

Go语言要求标识符以一个字母或下划线开头,后面可以跟任意数量的字母、数字、下划线。不能使用关键字作为标识符

区分大小写,变量num和变量Num是两个变量。

2.2. 声明

Go语言的变量声明方式和其他语言(如C、Java、Python)不太一样。

比如,我们声明一个为int类型的变量a:

var a int

可以看出,Go语言声明变量的方式为:

var <变量名> <变量类型>

我们还可以同时声明多个类型相同的变量:

var <变量名1>, <变量名2>, <变量名3>, ... <变量类型>

使用分组同时声明多个类型不同的变量:

var (
	<变量名1> <变量类型1>
    <变量名2> <变量类型2>
    <变量名3> <变量类型3>
    ...
)

下面是一个具体的例子:

package main

import "fmt"

var i bool//类型在后

func main() {
	var a, b, c int//多个
	fmt.Println(i, a, b, c)
}

2.3. 初始化

当我们声明变量时,可以对其进行初始化。当有初始值时,我们可以省略变量的类型,变量会根据对应的初始值获取正确的类型。见下例:

package main

import "fmt"

var a int = 1
var b, c bool = true, false

func main() {
	var i, j, k = 2, false, "行小观"	//省略变量类型
	fmt.Println(a, b, c, i, j, k)
    k = "行小观2号" //赋值操作
    fmt.Println(k)
}

若我们在声明变量时,不给变量赋初始值,则这些变量会被赋予“零值”。

这些零值为:

  1. 数值类型为0
  2. 布尔类型为false
  3. 字符串为""(即空字符串)

如果上例中的代码中的变量不进行初始化,即:

package main

import "fmt"

var a int
var b, c bool

func main() {
	var i int
	var j bool
	var k string
	fmt.Println(a, b, c, i, j, k)
}

则打印结果为:0 false false 0 false (变量k由于是空字符串,所以打印出来了但是看不到)

2.4. 短变量声明

前面介绍了当我们声明变量时有以下几种方式:

var i int	//声明一个int变量
var i, j, k int	//同时声明多个int变量
var i int = 1	//声明一个int变量并初始化
var i, j, k int = 1, 2, 3	//同时声明多个int变量并分别初始化
var i = 1	//省略类型,声明一个int变量并初始化
var i, j, k = 1, 2, 3	//省略类型,同时声明多个int变量并分别初始化

除此之外还有一种更简洁的声明变量的方式:

i := 1
i, j, k := 1, 2, 3

当我们使用:=声明变量时,不用写var也不用写类型,但是这种方式只能在函数内部使用,不能在函数外部使用。当在函数外部声明变量时,只能使用var

package main

import "fmt"

var a int = 1	//函数外部

func main() {
	var i, j int = 2, 3	//函数内部

	k := 4 //只能在函数中使用
	v1, v2, v3 := true, false, "行小观"

	fmt.Println(a, i, j, k, v1, v2, v3)
}

此外,我们声明的变量必须要使用,如果声明了变量,但是没使用,会在编译时报错。比如:

package main

import "fmt"

func main() {
	var i bool
	var j int //声明了,但没使用,会报错
	fmt.Println(i)
}

对于我们导入的包也有此要求,即:导入的包必须使用。

3. 数据类型

3.1. 布尔类型

布尔类型为bool,值可取truefalse,默认值为false

3.2. 字符串类型

字符串类型为string,默认为空字符串""

3.3. 数值类型

整数类型分为:

  • 有符号数:intint8int16int32 (rune)int64

  • 无符号数:uintuint8 (byte)uint16uint32uint64

其中intuint的两种类型的长度相同,取决于具体的编译器,比如在32位系统上通常为32位,在64位系统上通常为64位。

int8uint8这些类型则是Go语言直接定义好位数的类型。runebyteint32uint8的别名。

当我们需要使用整数时,应当尽量使用int类型。当然,如果你有特殊的理由使用其他整数类型,便另当他论。

浮点数类型有两种:float32float64,注意没有所谓的float类型。

复数类型也有两种:complex64complex128

注意:不同类型的变量之间不能直接进行赋值或其他运算(比如加减乘除)

package main

import "fmt"

var (
	a int = 1
	b int8 = 2
	c int16
)

func main() {
	c = b	//不同类型之间进行赋值操作,[报错1]
	d := a + b	//不同类型之间进行相加运算,[报错2]
	fmt.Printf("c = %v, d = %v", c, d)
}

以上代码在编译过程中会报错:

[报错1]:cannot use b (type int8) as type int16 in assignment

[报错2]:invalid operation: a + b (mismatched types int and int8)

3.4. 类型转换

前面一节说过:不同类型的变量之间不能直接进行赋值或其他运算,所以我们可以间接地做。

比如:将int8类型转换为int类型,这样就可以间接地进行赋值和其他运算。

使用表达式T(v)将变量v的值的类型转换为T。注意是转换的是变量的值,变量本身的类型不变。

package main

import "fmt"

var (
	a int = 1
	b int8 = 2
	c uint
	d int64
)

func main() {
	c = uint(b) //将变量b的值2的类型从int8转换为uint
	d = int64(a) + int64(b)

	fmt.Printf("c(%T):%v = b(%T):%v
", c, c, b, b)
	fmt.Printf("a(%T):%v + b(%T):%v = d(%T):%v
", a, a, b, b, d, d)
}

注意:Go语言中的类型转换是显示的,表达式T()是必须的,不能省略。

4. 常量

常量是固定的值,值在程序运行期间不会改变。

常量可以定义为数值、字符串、布尔类型

常量的声明方式和变量差不多,区别在于常量需要用const关键字修饰,不能使用:=进行声明。

package main

import "fmt"

const num int = 555
var a int = 1

func main() {

	const world = "世界"
	const truth = true

	fmt.Println("Hello,", world)
	fmt.Println("num = ", num)
	fmt.Println("a = ", a)
	fmt.Println("对吗?", truth)
}

5. 初识函数

如果你之前学习过C或者Java等语言,肯定已经对函数(方法)有了一定的认识。

简单地来说,函数是对能完成某个功能的部分代码的抽象。当以后再需要该功能,我们只需要调用其对用的函数即可,不必再重复编写代码。

5.1. 函数的声明

我们在前面的内容已经使用到了函数,即main()。我们使用func关键字声明函数。

func func_name() {
    
}

5.2. 函数的参数

Go语言中,函数可以有0个或多个参数。

package main

import "fmt"

func printName(name string, age int) {
	fmt.Println("我叫", name, ", 今年", age, "岁了")
}

func sayHello() {
	fmt.Println("行小观说:“你好”")
}

func main() {
	printName("行小观", 1)
	sayHello()
}

如果你有多个参数的类型相同,你可以进行简写,只需要在这几个相同的参数最后写一遍类型即可。

func foo(x int, y int, z int)
可以简写为:
func foo(x, y, x int)

5.3. 函数的类型和返回值

函数的类型在函数名之后。(尽快适应Go的这种风格:类型在变量名后)

package main

import "fmt"

func add(x int, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(1, 2))
}

当函数没有返回值时,不需要写函数的类型:

func sayHello() {//没有返回值,不写函数类型
	fmt.Println("行小观说:“你好”")
}

函数可以有0个或多个返回值

多个返回值就意味着该函数有多个返回值类型:

package main

import "fmt"

func sumAndDiff(x, y int) (int, int) { //两个返回值类型
	sum := x + y
	diff := x - y
	return sum, diff //两个返回值
}

func main() {
	a, b := sumAndDiff(5, 1)
	fmt.Println(a, b)
}

注意:和参数不同,有几个返回值就写几个返回值类型,不能简写。

Go语言还提供了另一种函数返回的方式:命名返回值。

顾名思义,我们通过给返回值进行命名,使用空return语句,这样会直接返回已命名的返回值。如上例的sumAndDiff函数可以写为:

func sumAndDiff(x, y int) (sum int, diff int) {//提前命名返回值
	sum = x + y
	diff = x - y //返回值在函数中被初始化
	return //返回值已经初始化了,不需要再在return语句中写变量了
}

下面总结一下函数的使用:

func functionName(input1, input11 type1, input2 type2 ...) (type1, type11, type2 ...){
    
    //函数体
    
    return value1, value11, value2 ...
}

或者命名返回值

func functionName(input1, input11 type1, input2 type2 ...) (output1 type1, output11 type11, output2 type2 ...){
    
    //函数体
    output1 = ...
    output11 = ...
    output2 =  ...
    ...
    return
}

6. 导出名

前面我们已经使用了import导入功能,比如improt "fmt",该行代码可以让我们在本包中使用其他包里的函数。

那么我们如何让其他包能够使用到本包的方法或变量呢?答案是:将方法或变量导出

在Go语言中,如果一个名字以大写字母开头,那么它就是已导出的,这意味着别的包可以使用它。(相当于Java中的public的作用)

比如我们常用的打印函数fmt.Println(...),可以看到Println()的首字母是大写的,所以我们能够导入fmt包后使用该方法。

7. 流程控制语句

7.1. if语句

if语句是条件判断语句,用来判断是否满足某种条件,如果满足,则执行某段代码;如果不满足,则不执行。

if ... {
    //代码
} else if ... {
    //代码
} else {
    //代码
}

注意格式:条件判断语句不需要使用小括号()

下面是几个例子:

if a > 0 {//如果满足a>0,则打印Hello, World
    fmt.Println("Hello, World")
}
if a > 0 {//如果满足a>0,则打印 Hello, World
    fmt.Println("Hello, World!")
} else {//否则(即不满足a>0),则打印 你好,世界!
    fmt.Println("你好,世界!")
}
if a > 5 {//如果满足a>5,则打印 Hello, World
    fmt.Println("Hello, World!")
} else if a <= 5 && a > 0 {//如果满足0<a<=5,则打印 好好学习,天天向上
    fmt.Println("好好学习,天天向上")
} else {//否则(即上面的条件都不满足),则打印 你好,世界!
    fmt.Println("你好,世界!")
}

Go语言的if语句有一个特性:可以在条件表达式前执行一个简单的语句。下面是一个例子:

package main

import "fmt"

func sum(x, y int) int {
	return x + y
}

func main ()  {
	if i := sum(1, 2); i > 0 {
		fmt.Println("Hello, World!")//作用域内,能打印i
	}
    //fmt.Println(i)//作用域外,不能打印i
}

在if语句中,使用sum(x, y int)函数计算出i的值,再进行判断。注意:变量i的作用域只在if语句中有效。

7.2. for语句

for语句是Go语言中的循环控制语句。它有几种形式:

(一)基本形式:

for 初始化语句; 条件表达式; 后置语句 {
    //循环体代码
}
  • 初始化语句:在第一次循环前之前,且只执行这一次
  • 条件表达式:每次循环都会计算该表达式,如果满足(值为true)则继续循环;如果不满足(值为false),则跳出循环
  • 后置语句:每次循环执行完都会执行该语句

下面是一个例子,循环打印5次"Hello,World!"

for i := 0; i < 5; i++ {
    fmt.Println("Hello, World!", i)
}

注意该例的初始化语句i := 0是一个短变量声明,变量i只在该for循环中生效。

(二)省略形式:

for循环中的初始化语句和后置语句是可以省略的。

i := 0
for ; i < 5; i++ {
    fmt.Println("Hello, World!", i)
}
i := 0
for ; i < 5; {
    fmt.Println("Hello, World!", i)
    i++
}

从某种意义上来讲,上面两个例子并没有省略初始化语句或后置语句,只是改变了位置。

(三)while形式

诸如C、Java等语言中都有while循环,但是Go语言中没有while循环,但是我们可以使用for循环来实现“while循环”。

其实(二)省略形式中的第二个for循环例子就已经可以看做是while循环了。我们再稍做改进:

i := 0
for i < 5 {//去掉两个分号,只写条件表达式
    fmt.Println("Hello, World!", i)
    i++
}

(四)无限循环形式

//打印无限多个Hello, World!
for  {
    fmt.Println("Hello, World!")
}

7.3. break和continue

上面提到的循环语句只有当条件表达式的值为false时,才会停止循环。但实际开发中,我们可能在条件表达式的值为true的情况下,需要退出循环。这种时候,就需要使用breakcontinue语句。

break语句用来跳出当前循环,continue语句用来跳过本次循环。

下面是两个实例(改进上面循环打印5次"Hello,World!"的例子):

实例1:增加需求,当打印完第2遍Hello,World!时,停止打印

for i := 0; i < 5; i++ {
    if i == 2 {
        break
    }
    fmt.Println("Hello, World!", i)
}

实例2:增加需求,不打印第3遍Hello,World!

for i := 0; i < 5; i++ {
    if i == 2 {
        continue
    }
    fmt.Println("Hello, World!", i)
}

Go语言入门系列(二)之基础语法总结
 
1. 认识HelloWorld
2. 变量
3. 数据类型
4. 常量
5. 初识函数
6. 导出名
7. 流程控制语句

7.4. switch语句

我们可以使用if...else if...else if...进行一连串的条件判断,但是这样过于繁杂。switch语句就是用来简化这个问题的。

switch 变量 {
    case 选项1 :
    	//操作1代码
    case 选项2 :
    	//操作2代码
    case 选项3 :
    	//操作3代码
    case 选项n:
    	//操作n代码
	default :
    	//默认操作
}

switch语句中有许多case和一个default,只有当变量和case的选项相匹配时,才会执行对应的操作代码。如果没有case的选项可以匹配,则默认执行default的代码。

下面是一个例子:

package main

import "fmt"

func sum(x, y int) int {
	return x + y
}

func main ()  {
    result := sum(3, 2)
	switch result {
	case 1 :
		fmt.Println("结果为1")
	case 2, 3, 4:	//多种情况聚合在一起
		fmt.Println("结果为2或3或4")
	case sum(1, 4):	//支持表达式
		fmt.Println("结果为5")
	default:
		fmt.Println("其他结果")
	}
}

从上面的例子可以看出,Go语言中switch的case支持常量(不必为整数)、表达式、多个值聚合。注意:不论是常量、表达式,还是多个值聚合,都要保证常量、表达式的值、多个值的类型和switch的变量相同。

switch语句的匹配顺序是自上到下。Go语言自动为每个case提供了break语句,所以在众多选项中只能执行1个casedefault,然后结束,剩余的不再执行。

但是可以使用fallthrough强制执行剩余的case:

result := sum(1, 1)
switch result {
    case 1 :
    fmt.Println("结果为1")
    fallthrough
    case 2, 3, 4:
    fmt.Println("结果为2或3或4")
    fallthrough
    case sum(1, 4):
    fmt.Println("结果为5")
    fallthrough
    default:
    fmt.Println("其他结果")
}

还是上面的那个例子,但是在每个case中使用fallthrough,现在的打印结果为:

结果为2或3或4
结果为5
其他结果

1. 认识HelloWorld

在前面的《Go语言入门系列(一)之Go的安装和使用》这篇文章中已经写过HelloWorld.go了,现在就来逐行认识一下它。

package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}

第1行:我们的Go程序是由——package构成的,包的声明形式为:package <包名>。该行的意思是:当前HelloWorld.go文件属于main包。

第2行:如果你使用过Java或Python,那你对import肯定不陌生。该行的意思是:导入一个名为fmt的包。如果需要导入多个包,有两种写法:

import "fmt"
import "math"

或者使用分组形式同时导入多个包

import (
	"fmt"
	"math/rand"
)

显然第二种使用括号,以分组的形式导入更加方便。

第3行:我们使用func关键字来声明一个函数,在这个例子中,我们声明的是main函数。如果你有过其他语言的编程经验,肯定熟悉main函数的作用:程序的入口。

第4行:我们的函数内容放在函数的{}中,在该例中,调用了fmt包中的打印方法,由此可见,Golang语言调用函数的方法和Java、Python一样使用小数点:<包名>.<函数名>

看完这几行简单代码,我们发现:在Go语言中,并不需要分号;来结束语句。

2. 变量

2.1. 命名规范

Go语言要求标识符以一个字母或下划线开头,后面可以跟任意数量的字母、数字、下划线。不能使用关键字作为标识符

区分大小写,变量num和变量Num是两个变量。

2.2. 声明

Go语言的变量声明方式和其他语言(如C、Java、Python)不太一样。

比如,我们声明一个为int类型的变量a:

var a int

可以看出,Go语言声明变量的方式为:

var <变量名> <变量类型>

我们还可以同时声明多个类型相同的变量:

var <变量名1>, <变量名2>, <变量名3>, ... <变量类型>

使用分组同时声明多个类型不同的变量:

var (
	<变量名1> <变量类型1>
    <变量名2> <变量类型2>
    <变量名3> <变量类型3>
    ...
)

下面是一个具体的例子:

package main

import "fmt"

var i bool//类型在后

func main() {
	var a, b, c int//多个
	fmt.Println(i, a, b, c)
}

2.3. 初始化

当我们声明变量时,可以对其进行初始化。当有初始值时,我们可以省略变量的类型,变量会根据对应的初始值获取正确的类型。见下例:

package main

import "fmt"

var a int = 1
var b, c bool = true, false

func main() {
	var i, j, k = 2, false, "行小观"	//省略变量类型
	fmt.Println(a, b, c, i, j, k)
    k = "行小观2号" //赋值操作
    fmt.Println(k)
}

若我们在声明变量时,不给变量赋初始值,则这些变量会被赋予“零值”。

这些零值为:

  1. 数值类型为0
  2. 布尔类型为false
  3. 字符串为""(即空字符串)

如果上例中的代码中的变量不进行初始化,即:

package main

import "fmt"

var a int
var b, c bool

func main() {
	var i int
	var j bool
	var k string
	fmt.Println(a, b, c, i, j, k)
}

则打印结果为:0 false false 0 false (变量k由于是空字符串,所以打印出来了但是看不到)

2.4. 短变量声明

前面介绍了当我们声明变量时有以下几种方式:

var i int	//声明一个int变量
var i, j, k int	//同时声明多个int变量
var i int = 1	//声明一个int变量并初始化
var i, j, k int = 1, 2, 3	//同时声明多个int变量并分别初始化
var i = 1	//省略类型,声明一个int变量并初始化
var i, j, k = 1, 2, 3	//省略类型,同时声明多个int变量并分别初始化

除此之外还有一种更简洁的声明变量的方式:

i := 1
i, j, k := 1, 2, 3

当我们使用:=声明变量时,不用写var也不用写类型,但是这种方式只能在函数内部使用,不能在函数外部使用。当在函数外部声明变量时,只能使用var

package main

import "fmt"

var a int = 1	//函数外部

func main() {
	var i, j int = 2, 3	//函数内部

	k := 4 //只能在函数中使用
	v1, v2, v3 := true, false, "行小观"

	fmt.Println(a, i, j, k, v1, v2, v3)
}

此外,我们声明的变量必须要使用,如果声明了变量,但是没使用,会在编译时报错。比如:

package main

import "fmt"

func main() {
	var i bool
	var j int //声明了,但没使用,会报错
	fmt.Println(i)
}

对于我们导入的包也有此要求,即:导入的包必须使用。

3. 数据类型

3.1. 布尔类型

布尔类型为bool,值可取truefalse,默认值为false

3.2. 字符串类型

字符串类型为string,默认为空字符串""

3.3. 数值类型

整数类型分为:

  • 有符号数:intint8int16int32 (rune)int64

  • 无符号数:uintuint8 (byte)uint16uint32uint64

其中intuint的两种类型的长度相同,取决于具体的编译器,比如在32位系统上通常为32位,在64位系统上通常为64位。

int8uint8这些类型则是Go语言直接定义好位数的类型。runebyteint32uint8的别名。

当我们需要使用整数时,应当尽量使用int类型。当然,如果你有特殊的理由使用其他整数类型,便另当他论。

浮点数类型有两种:float32float64,注意没有所谓的float类型。

复数类型也有两种:complex64complex128

注意:不同类型的变量之间不能直接进行赋值或其他运算(比如加减乘除)

package main

import "fmt"

var (
	a int = 1
	b int8 = 2
	c int16
)

func main() {
	c = b	//不同类型之间进行赋值操作,[报错1]
	d := a + b	//不同类型之间进行相加运算,[报错2]
	fmt.Printf("c = %v, d = %v", c, d)
}

以上代码在编译过程中会报错:

[报错1]:cannot use b (type int8) as type int16 in assignment

[报错2]:invalid operation: a + b (mismatched types int and int8)

3.4. 类型转换

前面一节说过:不同类型的变量之间不能直接进行赋值或其他运算,所以我们可以间接地做。

比如:将int8类型转换为int类型,这样就可以间接地进行赋值和其他运算。

使用表达式T(v)将变量v的值的类型转换为T。注意是转换的是变量的值,变量本身的类型不变。

package main

import "fmt"

var (
	a int = 1
	b int8 = 2
	c uint
	d int64
)

func main() {
	c = uint(b) //将变量b的值2的类型从int8转换为uint
	d = int64(a) + int64(b)

	fmt.Printf("c(%T):%v = b(%T):%v
", c, c, b, b)
	fmt.Printf("a(%T):%v + b(%T):%v = d(%T):%v
", a, a, b, b, d, d)
}

注意:Go语言中的类型转换是显示的,表达式T()是必须的,不能省略。

4. 常量

常量是固定的值,值在程序运行期间不会改变。

常量可以定义为数值、字符串、布尔类型

常量的声明方式和变量差不多,区别在于常量需要用const关键字修饰,不能使用:=进行声明。

package main

import "fmt"

const num int = 555
var a int = 1

func main() {

	const world = "世界"
	const truth = true

	fmt.Println("Hello,", world)
	fmt.Println("num = ", num)
	fmt.Println("a = ", a)
	fmt.Println("对吗?", truth)
}

5. 初识函数

如果你之前学习过C或者Java等语言,肯定已经对函数(方法)有了一定的认识。

简单地来说,函数是对能完成某个功能的部分代码的抽象。当以后再需要该功能,我们只需要调用其对用的函数即可,不必再重复编写代码。

5.1. 函数的声明

我们在前面的内容已经使用到了函数,即main()。我们使用func关键字声明函数。

func func_name() {
    
}

5.2. 函数的参数

Go语言中,函数可以有0个或多个参数。

package main

import "fmt"

func printName(name string, age int) {
	fmt.Println("我叫", name, ", 今年", age, "岁了")
}

func sayHello() {
	fmt.Println("行小观说:“你好”")
}

func main() {
	printName("行小观", 1)
	sayHello()
}

如果你有多个参数的类型相同,你可以进行简写,只需要在这几个相同的参数最后写一遍类型即可。

func foo(x int, y int, z int)
可以简写为:
func foo(x, y, x int)

5.3. 函数的类型和返回值

函数的类型在函数名之后。(尽快适应Go的这种风格:类型在变量名后)

package main

import "fmt"

func add(x int, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(1, 2))
}

当函数没有返回值时,不需要写函数的类型:

func sayHello() {//没有返回值,不写函数类型
	fmt.Println("行小观说:“你好”")
}

函数可以有0个或多个返回值

多个返回值就意味着该函数有多个返回值类型:

package main

import "fmt"

func sumAndDiff(x, y int) (int, int) { //两个返回值类型
	sum := x + y
	diff := x - y
	return sum, diff //两个返回值
}

func main() {
	a, b := sumAndDiff(5, 1)
	fmt.Println(a, b)
}

注意:和参数不同,有几个返回值就写几个返回值类型,不能简写。

Go语言还提供了另一种函数返回的方式:命名返回值。

顾名思义,我们通过给返回值进行命名,使用空return语句,这样会直接返回已命名的返回值。如上例的sumAndDiff函数可以写为:

func sumAndDiff(x, y int) (sum int, diff int) {//提前命名返回值
	sum = x + y
	diff = x - y //返回值在函数中被初始化
	return //返回值已经初始化了,不需要再在return语句中写变量了
}

下面总结一下函数的使用:

func functionName(input1, input11 type1, input2 type2 ...) (type1, type11, type2 ...){
    
    //函数体
    
    return value1, value11, value2 ...
}

或者命名返回值

func functionName(input1, input11 type1, input2 type2 ...) (output1 type1, output11 type11, output2 type2 ...){
    
    //函数体
    output1 = ...
    output11 = ...
    output2 =  ...
    ...
    return
}

6. 导出名

前面我们已经使用了import导入功能,比如improt "fmt",该行代码可以让我们在本包中使用其他包里的函数。

那么我们如何让其他包能够使用到本包的方法或变量呢?答案是:将方法或变量导出

在Go语言中,如果一个名字以大写字母开头,那么它就是已导出的,这意味着别的包可以使用它。(相当于Java中的public的作用)

比如我们常用的打印函数fmt.Println(...),可以看到Println()的首字母是大写的,所以我们能够导入fmt包后使用该方法。

7. 流程控制语句

7.1. if语句

if语句是条件判断语句,用来判断是否满足某种条件,如果满足,则执行某段代码;如果不满足,则不执行。

if ... {
    //代码
} else if ... {
    //代码
} else {
    //代码
}

注意格式:条件判断语句不需要使用小括号()

下面是几个例子:

if a > 0 {//如果满足a>0,则打印Hello, World
    fmt.Println("Hello, World")
}
if a > 0 {//如果满足a>0,则打印 Hello, World
    fmt.Println("Hello, World!")
} else {//否则(即不满足a>0),则打印 你好,世界!
    fmt.Println("你好,世界!")
}
if a > 5 {//如果满足a>5,则打印 Hello, World
    fmt.Println("Hello, World!")
} else if a <= 5 && a > 0 {//如果满足0<a<=5,则打印 好好学习,天天向上
    fmt.Println("好好学习,天天向上")
} else {//否则(即上面的条件都不满足),则打印 你好,世界!
    fmt.Println("你好,世界!")
}

Go语言的if语句有一个特性:可以在条件表达式前执行一个简单的语句。下面是一个例子:

package main

import "fmt"

func sum(x, y int) int {
	return x + y
}

func main ()  {
	if i := sum(1, 2); i > 0 {
		fmt.Println("Hello, World!")//作用域内,能打印i
	}
    //fmt.Println(i)//作用域外,不能打印i
}

在if语句中,使用sum(x, y int)函数计算出i的值,再进行判断。注意:变量i的作用域只在if语句中有效。

7.2. for语句

for语句是Go语言中的循环控制语句。它有几种形式:

(一)基本形式:

for 初始化语句; 条件表达式; 后置语句 {
    //循环体代码
}
  • 初始化语句:在第一次循环前之前,且只执行这一次
  • 条件表达式:每次循环都会计算该表达式,如果满足(值为true)则继续循环;如果不满足(值为false),则跳出循环
  • 后置语句:每次循环执行完都会执行该语句

下面是一个例子,循环打印5次"Hello,World!"

for i := 0; i < 5; i++ {
    fmt.Println("Hello, World!", i)
}

注意该例的初始化语句i := 0是一个短变量声明,变量i只在该for循环中生效。

(二)省略形式:

for循环中的初始化语句和后置语句是可以省略的。

i := 0
for ; i < 5; i++ {
    fmt.Println("Hello, World!", i)
}
i := 0
for ; i < 5; {
    fmt.Println("Hello, World!", i)
    i++
}

从某种意义上来讲,上面两个例子并没有省略初始化语句或后置语句,只是改变了位置。

(三)while形式

诸如C、Java等语言中都有while循环,但是Go语言中没有while循环,但是我们可以使用for循环来实现“while循环”。

其实(二)省略形式中的第二个for循环例子就已经可以看做是while循环了。我们再稍做改进:

i := 0
for i < 5 {//去掉两个分号,只写条件表达式
    fmt.Println("Hello, World!", i)
    i++
}

(四)无限循环形式

//打印无限多个Hello, World!
for  {
    fmt.Println("Hello, World!")
}

7.3. break和continue

上面提到的循环语句只有当条件表达式的值为false时,才会停止循环。但实际开发中,我们可能在条件表达式的值为true的情况下,需要退出循环。这种时候,就需要使用breakcontinue语句。

break语句用来跳出当前循环,continue语句用来跳过本次循环。

下面是两个实例(改进上面循环打印5次"Hello,World!"的例子):

实例1:增加需求,当打印完第2遍Hello,World!时,停止打印

for i := 0; i < 5; i++ {
    if i == 2 {
        break
    }
    fmt.Println("Hello, World!", i)
}

实例2:增加需求,不打印第3遍Hello,World!

for i := 0; i < 5; i++ {
    if i == 2 {
        continue
    }
    fmt.Println("Hello, World!", i)
}

Go语言入门系列(二)之基础语法总结
 
1. 认识HelloWorld
2. 变量
3. 数据类型
4. 常量
5. 初识函数
6. 导出名
7. 流程控制语句

7.4. switch语句

我们可以使用if...else if...else if...进行一连串的条件判断,但是这样过于繁杂。switch语句就是用来简化这个问题的。

switch 变量 {
    case 选项1 :
    	//操作1代码
    case 选项2 :
    	//操作2代码
    case 选项3 :
    	//操作3代码
    case 选项n:
    	//操作n代码
	default :
    	//默认操作
}

switch语句中有许多case和一个default,只有当变量和case的选项相匹配时,才会执行对应的操作代码。如果没有case的选项可以匹配,则默认执行default的代码。

下面是一个例子:

package main

import "fmt"

func sum(x, y int) int {
	return x + y
}

func main ()  {
    result := sum(3, 2)
	switch result {
	case 1 :
		fmt.Println("结果为1")
	case 2, 3, 4:	//多种情况聚合在一起
		fmt.Println("结果为2或3或4")
	case sum(1, 4):	//支持表达式
		fmt.Println("结果为5")
	default:
		fmt.Println("其他结果")
	}
}

从上面的例子可以看出,Go语言中switch的case支持常量(不必为整数)、表达式、多个值聚合。注意:不论是常量、表达式,还是多个值聚合,都要保证常量、表达式的值、多个值的类型和switch的变量相同。

switch语句的匹配顺序是自上到下。Go语言自动为每个case提供了break语句,所以在众多选项中只能执行1个casedefault,然后结束,剩余的不再执行。

但是可以使用fallthrough强制执行剩余的case:

result := sum(1, 1)
switch result {
    case 1 :
    fmt.Println("结果为1")
    fallthrough
    case 2, 3, 4:
    fmt.Println("结果为2或3或4")
    fallthrough
    case sum(1, 4):
    fmt.Println("结果为5")
    fallthrough
    default:
    fmt.Println("其他结果")
}

还是上面的那个例子,但是在每个case中使用fallthrough,现在的打印结果为:

结果为2或3或4
结果为5
其他结果