分享

Go 语言入门教程(二)

 夜猫速读 2022-05-05 发布于湖北

Go 语言的赋值

上节课我们学习了 Go 语言中的两种变量声明方式:单变量声明方式和多变量声明方式。既然已经声明了变量,那么下一步肯定要给变量赋值并使用,这节课我们就来学习下在 Go 语言中如何给一个变量赋值:

1. 单变量赋值

Go 语言的赋值使用的是 = 符号,赋值过程可以在变量声明时赋值,也可以在变量声明之后赋值,如果在变量声明时直接赋值,可以不用声明变量类型。需要注意的是 Go 语言变量声明之后会初始化一个"零值",即使不赋值也可以直接使用。我们来通过一个例子来深入了解变量的赋值和"零值"以及声明时赋值:

Tips:变量的数据类型我们会在后面的小节进行深入讲解,这个小节中只是简单了解下。

package main

import "fmt"

func main() {
var num1 int
fmt.Println("num1的零值:", num1)
num1 = 10 // 使用=对num1进行赋值操作
fmt.Println("num1的值:", num1)
var num2 = 20 //在声明变量时,使用 = 对num2 进行赋值操作
fmt.Println("num2的值:", num2)
}
  • 第 6 行:声明了一个名为 num1 的 int 类型变量;

  • 第 7 行:输出变量 num1 的零值;

  • 第 8 行:对 num1 变量重新赋值,使其值变为 10;

  • 第 9 行:打印重新赋值之后的 num1 变量的值;

  • 第 10 行:声明一个名为 num2 的变量,并直接对其赋值为 20;

  • 第 11 行:打印 num2 变量的值。

输出结果:

控制台中输出了 num1,num2 的值

从输出的结果可以看出,声明了变量 num1 之后,num1 就已经具有了零值:0,可以直接拿来进行使用而程序并不会报错。之后对 num1 进行赋值,改变了 num1 的值,使其值变为了 10。在声明变量 num2 的时候没有给予 num2 变量类型,就直接赋值了,这个是 Go 语言的特性。Go 语言可以在声明的时候直接不定义类型赋值,其声明的变量类型和赋值的类型一致

2. 多变量赋值

Go 语言中的=符号,不仅仅可以给一个变量赋值,它可以赋值复数的变量,形如变量,变量=变量值,变量值,复数变量和变量值之间使用,隔开。多变量和单变量赋值的使用方法一致。

package main

import (
"fmt"
)

func main() {
var num1, num2 = 10, 20 //使用,分割从而进行多变量赋值
fmt.Println("num1,num2的值:", num1, num2)
num1, num2 = 30, 40 //使用,分割从而进行多变量赋值
fmt.Println("num1,num2的值:", num1, num2)
}
  • 第 8 行:声明两个变量 num1 和 num2 并直接给这两个变量分别赋值为 10,20;

  • 第 9 行:打印两个变量的值;

  • 第 10 行:修改两个变量的值为 30,40;

  • 第 11 行:修改之后重新打印两个变量的值。

输出结果:

控制台中输出了 num1,num2 的值

3. 小结

本文主要学习了 Go 语言中的赋值办法,直接在声明时赋值可以不带类型,Go 语言会自动根据变量值自动匹配变量类型。但是要注意的是:如果你在声明变量的同时也标明了变量的数据类型,那么在之后的使用中一定要注意在一开始的时候变量的数据类型。

Go 语言的 :=

前面两个小节我们分别学习了 Go 语言中的变量声明和赋值。按照一贯的思维,变量肯定是要先声明然后才能被赋值并使用。但是在 Go 语言中新增了一个特殊的运算符 := ,这个运算符可以使变量在不被声明的情况下直接使用,这节课我们就来具体看下这个特殊的运算符:

1. 单变量 :=

Go 语言中新增了一个特殊的运算符:=,这个运算符可以使变量在不声明的情况下直接被赋值使用。其使用方法和带值声明变量类似,只是少了var关键字,形如变量名:=变量值,这样就等于声明了一个带值的变量,该变量的类型与其变量值一致

实例演示

package main

import "fmt"

func main() {
helloWorld := "Hello World!"
fmt.Println(helloWorld)
}

运行案例点击 "运行案例" 可查看在线运行效果

package main

import "fmt"

func main() {
helloWorld := "Hello World!"
fmt.Println(helloWorld)
}
  • 第 3 行:直接为变量 helloWorld 赋值为 “Hello World”;

  • 第 4 行:打印变量 helloWorld 。

输出结果:

程序运行结果

可以看到,上面的代码中我们并没有提前对 helloworld 这个变量进行声明,而是直接就拿来用了,而且程序也没有报错,控制台也正常打印出了 “Hello World!”。 := 符号的出现省去了我们大量的编写变量声明的语句,在实际的开发中我们一般使用这种形式来声明变量。

2. 多变量 :=

在 Go 语言的多变量赋值体系中,也支持了:=运算符。你可以使用形如变量名,变量名:=变量值,变量值的形式来进行多变量操作。其使用方法和多变量带值声明类似,只是少了var关键字。

package main

import "fmt"

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

输出结果:

程序运行结果

在 Go 语言中为了使开发更高效,更多的会使用 := 这种 Go 语言独有的赋值方式,一开始使用也许会有些不适应,上手之后简直不要太好用。

3. 小结

:= 这个运算符和 = 同样可以进行单变量以及多变量的赋值。需要注意的是,在使用:=给变量赋值的时候,要看一下这个变量是否已经声明过了,如果声明过了就不需要使用 := 了。

Go 语言的整型(int)数据类型

还记得我们之前在第 7 小节和第 8 小节中提到的变量数据类型的概念吗?从这个小节开始到后面的几个小节中我们都会进行对 Go 语言中的数据类型相关知识点进行讲解,本节课我们主要讲解一下 Go 语言中处理带符号的整数的数据类型。

1. 定长类型

在 Go 语言中整形数据类型被细致地划分为了下面几种,根据可以存储数据的长度分为:

序号类型长度
1int8-128~127
2int16-32768~32767
3int32-2147483648~2147483647
4int64-9223372036854775808~9223372036854775807

2. 不定长类型

在 Go 语言中也实现了随着平台位数变化而变化的数据类型int。一般来说,这个类型在32位的系统中长度和int32一致,在64位的系统中长度和int64一致。

package main

import (
"fmt"
"math"
)

func main() {
var num int
num = math.MaxInt64//将e赋予int64的最大值:9223372036854775807
fmt.Println(num)
}

在 64 位操作系统环境中执行结果:

64 位操作系统执行结果

在 32位 操作系统环境中,因为int的长度与int32相等了,只有32位,所以执行会报超出取值范围的错误:

32 位操作系统执行结果

3. 各类型的互相转换

Go 语言是强类型语言,各个虽然同是整型,但是不同整型的变量不允许直接赋值,需要进行强制类型转换,同时长度大的整型向长度小的整型转换时,要考虑溢出问题。而且不同类的整型无法进行运算,想要进行运算必须要进行强制类型转换,使他们都变成同一类型之后,再运算。举一个int8int16类型的变量赋值与计算的例子:

package main

import (
"fmt"
"math"
)

func main() {
var a int8 = math.MaxInt8
var b int16 = math.MaxInt8 + 1
fmt.Println(a, b)

a = int8(b)
fmt.Println(a, b) //因为b长度过长,在转换为int8的过程中溢出了

//整型变量可以和常数进行计算
a = a + 1
b = b + 1
fmt.Println(a, b)

//不同类型的整型变量计算必须强转为相同类型,一般转换为长度大的来计算
c := int16(a) + b
fmt.Println(c)
}

输出结果:

各类型互相转换输出结果

3. 小结

这一小节中我们主要介绍了有符号整形数据类型,整形数据类型根据可以存储的数据长度分为了: int8 、 int16 、 int32 、 int64 ,我们在使用的时候要根据条件需求来决定变量的数据类型,同时也要注意高精度向低精度转失真的风险。

Go 语言的无符号整型(uint)

上个小节我们主要学习了 Go 语言中的整型 int 数据类型,本小节主要介绍了 Go 语言中处理无符号的整数的数据类型。

1. 定长类型

序号类型长度
1uint80~255
2uint160~65535
3uint320~4294967295
4uint640~18446744073709551615

2. 不定长类型

在 Go 语言中也实现了随着平台位数变化而变化的数据类型uint。一般来说,这个类型在32位的系统中长度和uint32一致,在64位的系统中长度和uint64一致。

package main

import (
"fmt"
"math"
)

func main() {
var num uint
num = math.MaxUint64 //将e赋予uint64的最大值:18446744073709551615
fmt.Println(num)
}

在 64 位环境中执行结果:

64 位操作系统执行结果

在 32 位环境中,因为int的长度与int32相等了,只有32位,所以执行时会报超出取值范围的错误:

64 位操作系统执行结果

3. 各类型的互相转换

Go 语言是强类型语言,各个虽然同是无符号整型,但是不同无符号整型的变量不允许直接赋值,需要进行强制类型转换,同时长度大的无符号整型向长度小的无符号整型转换时,要考虑溢出问题。而且不同类的整型无法进行运算,想要进行运算必须要进行强制类型转换,使他们都变成同一类型之后,再运算。举一个 uint8 和 uint16 类型的变量赋值与计算的例子:

package main

import (
"fmt"
"math"
)

func main() {
var a uint8 = math.MaxUint8
var b uint16 = math.MaxUint8 + 1
fmt.Println(a, b)

a = uint8(b)
fmt.Println(a, b) //因为b长度过长,在转换为uint8的过程中溢出了

//无符号整型变量可以和常数进行计算
a = a + 1
b = b + 1
fmt.Println(a, b)

//不同类型的无符号整型变量计算必须强转为相同类型,一般转换为长度大的来计算
c := uint16(a) + b
fmt.Println(c)
}

输出结果:

各类型相互转换输出结果

4. 小结

本文主要学习了 Go 语言中的无符号整型的使用,注意高精度向低精度转失真的风险。

Go 语言的浮点型(float)

前面两个小节我们我们都是在讲解整型的数据类型,也就是说都是整数,但是在开发中我们也会经常使用小数数据,这节课我们就主要介绍 Go 语言中处理小数的数据类型

1. 实数类型

Go 语言提供了两种精度的浮点数 float32 和 float64,它们的算术规范由 IEEE754 浮点数国际标准定义,该浮点数规范被所有现代的 CPU 支持。

序号类型长度
1float321.401298464324817e-45~3.4028234663852886e+38
2float645e-324~1.7976931348623157e+308

2. 复数类型

序号类型长度
1complex64实部和虚部都是一个float32
2complex128实部和虚部都是一个float64

3. 使用示例

通过几个示例加深对这几个数据类型的理解。

3.1 实数类型示例

在 Go 语言中小数值类型取决于计算机操作系统的位数,我是使用的 64位 的计算机,所以使用:=时,会得到一个类型为 float64 的变量

package main

import (
"fmt"
)

func main() {
var a float32
a = 1.2
fmt.Println("a = ", a) // 此处的结果

//自动推导类型
b := 1.2
fmt.Printf("b type is %T\n", b)
fmt.Println("b = ", b)
}

输出结果:

实数类型示例输出结果

3.2 复数类型示例

在 Go 语言中复数值类型取决于计算机操作系统的位数,我是使用的 64 位的计算机,所以使用:=时,会得到一个类型为 complex128 的变量

package main

import (
"fmt"
)

func main() {
var a complex64
a = 1.2 + 2.22i
fmt.Println("a = ", a) // 此处的结果

//自动推导类型
b := 1.2 + 3.45i
fmt.Printf("b type is %T\n", b)
fmt.Println("b = ", b)

//通过内建函数取实部和虚部
fmt.Println("real(b) = ", real(b), " , imag(b) = ", imag(b))
}

输出结果:

复数类型示例输出结果

4. 小结

本文主要学习了 Go 语言中的浮点型的使用,注意高精度向低精度转失真的风险。

Go 语言的字符类型

字符类型在工作中也会非常频繁地用到,是一个非常重要的数据类型。本文主要介绍了 Go 语言中处理字符和字符串的数据类型。

1. 字符和字符串类型

序号类型说明
1byteuint8 类型的别名,同等于 uint8。一般用于表示 ASCII 字符,即只能操作简单的字符,不支持中文操作
2runeint32 类型的别名,同等于 int32。一般用于表示 Unicode 字符,即可以处理任何字符
3string一个指向 byte 数组的指针,可以为空字符串不可为nil

2. 代码演示

接下来使用一段代码来更清晰地解释byterune的区别,以及了解这三个类型的关系。

package main

import "fmt"

//将字符串转换为rune的数组,并替换数组第i个元素为ch
func str2Rune(str *string, i int, ch rune) {
temp := []rune(*str)
temp[i] = ch
*str = string(temp)
}

//将字符串转换为byte的数组,并替换数组第i个元素为ch
func str2Byte(str *string, i int, ch byte) {
temp := []byte(*str)
temp[i] = ch
*str = string(temp)
}

func main() {
str := "你好 hello"
str1 := "你好 hello"
str2 := "你好 hello"
str2Rune(&str, 0, 'A') //将第0个字符替换为A
str2Byte(&str1, 0, 'A') //将第0个字符替换为A
str2Byte(&str2, 7, 'A') //将第7个字符替换为A
fmt.Println("rune 数组处理中文后:", str)
fmt.Println("byte 数组处理中文后:", str1)
fmt.Println("byte 数组处理英文后:", str2)
}

输出结果:

byte 和 rune 区别实例输出结果

结论:

  • string可以直接转换为rune或者byte数组;

  • runebyte可以互相转换;

  • byte 的操作单位是一个字节,可以理解为一个英文字符;

  • rune 的操作单位是一个字符,不管这个字符是什么字符。

3. 小结

本文主要学习了 Go 语言中的字符类型的使用,注意 byte 和 rune 使用上的区别。

本文主要介绍了Go语言中处理布尔类型数据的数据类型。布尔类型的数据表示逻辑运算结果,有以
下两种取值:

  • 真,使用 True 关键字表示。

  • 假,使用 False 关键字表示。

1.布尔类型

序号类型说明
1bool只能存放true或者false

2.使用示例

package main

import "fmt"

func main() {
var varb bool
varb = true
fmt.Println(varb)
}

输出结果:

bool 类型实例输出结果

3.小结

本文主要学习了 Go 语言中的布尔型的数据类型使用。Go 语言中 bool 类型变量,只能存放 true 或者 false 。不可以放置其它的任何值,而且不存在0或者1的自动转换。

Go 语言的强制类型转换

Go 语言是一种强类型语言,而且没有隐式转换。也就是说运算符左右的变量类型必须一致,若不一致就会报错。为了使用户更加的容易使用,所以 Go 语言提供了各个类型之间强制类型转换的内置方法。

1. 整型和浮点型互相转换

整型浮点型变量之间的相互转换相对容易,只需使用强制类型转换标志 type(variable)就好了。需要注意的是,当高精度低精度类型转换的时候,会失真。即浮点型向整型转换的时候会失去其小数部分。在实际开发的过程中,我们一般要避免这两个类型的互相转换,在无法避免的场景,比如说计算浮点数和整数的和之类的情况中。需要秉持不失真原则,将低精度向高精度转换之后进行计算。

代码示例:

package main

import "fmt"

func main(){
var a int = 10 // 声明一个整形变量 a 并给 a 赋值为 10
var b float32 = 3.14 // 声明一个浮点型变量 b 并给 b 赋值为 3.14

fmt.Printf("整型转换为浮点型:%f\n",float32(a)) // 将变量 a 强制转换为浮点型变量并打印结果
fmt.Printf("浮点型转换为整型:%d\n",int(b)) //浮点型转为整型会失真
}

执行结果如下:

整型和浮点型互相转换实例输出结果

2. 整形和字符串互相转换

整型和字符串类型的变量互相转换,需要依靠 Go 语言提供的转换包strconv。字符串转整型需要使用这个包的Atoi(string)方法,整型转字符串则是Itoa(int)。这种转换用得最多的就是给一些对象进行编号。比如需要给张三编号为NO.1,你可能需要将1转换为字符串之后与NO.进行拼接。

代码示例:

package main

import (
"fmt"
"strconv" // 在程序中导入 strconv 转环包
)

func main() {
var a int = 10 // 定义一个整形变量并赋值为 10
var b string = "10" // 定义一个字符串类型变量并赋值为 "10"

fmt.Printf("整型转换为字符串:%s\n", strconv.Itoa(a))
tmp, _ := strconv.Atoi(b)
fmt.Printf("字符串转换为整型:%d\n", tmp)
}

执行结果如下:

整形和字符串互相转换实例输出结果

3. 浮点型和字符串互相转换

浮点型和字符串的互相转换没有直接封装好的转换接口了,需要调用strconvs包中稍微底层一点的接口。浮点型转字符串使用FormatFloat(float64,byte,int,int)方法,字符串转换为浮点型则使用ParseFloat(...)方法。因为浮点数在存储过程中容易因为精度问题而存在误差,所以有时候会将浮点数转换为字符串进行存储。

代码示例:

package main

import (
"fmt"
"strconv"
)

func main() {
f1 := 0.123456789
s1 := strconv.FormatFloat(f1, 'f', -1, 32)
s2 := strconv.FormatFloat(f1, 'f', -1, 64)
s3 := "0.123456789"
f2, _ := strconv.ParseFloat(s3, 64)
f3, _ := strconv.ParseFloat(s3, 32)
fmt.Println("将浮点数转换为float32转换为string:", s2)
fmt.Println("将float64转换为string:", s1)
fmt.Println("将string转换为float64:", f2)
fmt.Println("将string转换为float32再强制转换为float64:", f3)
}

执行结果:

浮点型和字符串互相转换实例输出结果

4. 小结

本文主要学习了 Go 语言中各个数据类型的互相强制转换。主要都是依赖与 strconvs 这个第三方包。这个包中还提供了其它很多的转换方法,大家有机会可以更深入地去了解一下。在做类型转换的时候要注意:浮点型在转为整型时会失真。

Go 语言的常量

常量可以理解为是一个存储了不可以改变的值的变量。常量主要用于特殊值的语义化,使这些值在更容易维护的情况下不会被程序所修改。Go 语言中声明常量使用的关键字是const。常量的使用非常广泛,比如说圆周率,再比如说一些明确的错误信息等一些容易被多次使用的值,一般都会使用常量进行实例化,使其在需要更改时,更容易维护,同时增加代码可读性。

1. 单常量定义

常量定义的形式为 const 常量名 常量类型 = 常量值

代码示例:

package main  

import (
"fmt"
)

const c1 string = "2020年3月8日"
const c2 = "2020年3月8日" //和变量一样,常量也可以不使用数据类型直接赋值,其类型和值一致

func main() {
fmt.Println(c1)
fmt.Println(c2)
}

代码块

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

输出结果:

2. 多常量定义

2.1 普通方式

和 Go 语言的变量一样,常量也可以进行多常量定义。定义形式为const 常量名,常量名= 常量值,常量值

代码示例:

package main  

import (
"fmt"
)

const c1, c2 = "2020年3月8日", "2020年3月9日"

func main() {
fmt.Println(c1)
fmt.Println(c2)
}

代码块

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

输出结果:

2.2 特殊方式

在常量的使用中,Go 语言还提供了一种特殊的多常量定义方式——const()。这种定义方式也是比较推荐的常量使用方式。

代码示例:

package main  

import (
"fmt"
)

const (
c1 = "2020年3月8日"
c2 = "2020年3月9日"
)

func main() {
fmt.Println(c1)
fmt.Println(c2)
}

输出结果:

3. 小结

本文主要学习了 Go 语言中常量的使用,在单常量定义时使用const,多常量时使用const()。常量和变量的声明基本一致,主要区别在于常量的值无法修改。常量的这个特性就使其可以将一些不希望被修改的值实例化为常量使用,比如圆周率之类的。

Go 语言中代替枚举的办法

枚举类型用于声明一组命名的常量,当一个变量有几种可能的取值时,可以将它定义为枚举类型。在 Go 语言中,并没有提供枚举类型,但是枚举类型又是开发过程中非常重要的数据类型。因为它可以事先定义一组有效的值,可以有效地防止用户提交无效数据,抽象到业务场景中就是我们平时网页上遇到的下拉框,或者我们选择快递地址时的省市信息,均为枚举类型的用武之地。所以在 Go 语言中对常量进行了一定的扩展,使其可以完美地替代枚举类型。

1.常量中的iota

为了使常量可以更好地替代枚举类型,Go 语言提供了一个iota关键字。使用iota初始化常量,可以生成一组规则类似的常量,但是不用每个常量都写一遍表达式。在一个const()表达式中,从iota开始的常量会被置为0,向后每个常量的值为前一个常量的值加一

代码示例:

package main

import (
"fmt"
)

type Weekday int //自定义一个星期类型,作为枚举类型

const (
Sun Weekday = iota
Mon
Tues
Wed
Thur
Fri
Sat
)

func main() {
fmt.Println("Sun :", Sun)
fmt.Println("Mon :", Mon)
fmt.Println("Tues:", Tues)
fmt.Println("Wed :", Wed)
fmt.Println("Thur:", Thur)
fmt.Println("Fri :", Fri)
fmt.Println("Sat :", Sat)
}

Tips:自定义数据类型会在Go语言拓展已有类型中详细介绍。这里可以简单地理解为定义了一个Weekday的枚举。

执行结果

2. 将枚举值转换为字符串

使用iota是可以使用 Go 语言的常量代替枚举类型,但是由于输出值均为阿拉伯数字,给调试和辨识造成了一定的困难。为了解决这一问题,Go 语言还提供了使常量枚举值输出为字符串的办法。需要我们手动构造一个使用枚举类型输出字符串的方法。

Tips:用的比较少,稍作了解即可

代码示例:

package main

import (
"fmt"
)

type Weekday int //自定义一个星期类型,作为枚举类型

const (
Sun Weekday = iota
Mon
Tues
Wed
Thur
Fri
Sat
)

func (w Weekday) String() string {
switch w {
case Sun:
return "Sun"
case Mon:
return "Mon"
case Tues:
return "Tues"
case Wed:
return "Wed"
case Thur:
return "Thur"
case Fri:
return "Fri"
case Sat:
return "Sat"
}
//不存在的枚举类型就返回"N/A"
return "N/A"
}

func main() {
fmt.Println("Sun :", Sun)
fmt.Println("Mon :", Mon)
fmt.Println("Tues:", Tues)
fmt.Println("Wed :", Wed)
fmt.Println("Thur:", Thur)
fmt.Println("Fri :", Fri)
fmt.Println("Sat :", Sat)
}

执行结果

3. 小结

本文主要介绍了如何使用 Go 语言中的常量来代替枚举类型。主要有两个要点:

  • 自定义枚举类型,第一个常量使用iota来赋值。

  • 手动构建String()方法,使常量输出为字符串。

Go 语言中的运算符

本文主要介绍 Go语言中的各种运算符的使用以及其优先级的比较。Go 语言中运算符分为下面几大类:

  • 算数运算符;

  • 关系运算符;

  • 逻辑运算符;

  • 位运算符;

  • 复制运算符。

下面我们就来一一看下这几种运算符如何使用。

1. Go 语言的算数运算符

Go语言中的算数运算符如表所示:

运算符结合性描述
+从左到右运算符左边的实体加上右边的实体
-从左到右运算符左边的实体减去右边的实体
*从左到右运算符左边的实体乘以右边的实体
/从左到右运算符左边的实体除以右边的实体
%从左到右运算符左边的实体对右边的实体取余
++从右到左左边的变量使用后自加一
从右到左左边的变量使用后自减一

代码示例:

package main

import (
"fmt"
)

func main() {
var a = -7
var b = 4

fmt.Println("a + b =", a+b)
fmt.Println("a - b =", a-b)
fmt.Println("a * b =", a*b)
fmt.Println("a / b =", a/b)
fmt.Println("a % b =", a%b)

//++和--只能独立为一条语句使用
a++
fmt.Println("a++:", a)
b--
fmt.Println("b--:", b)
}

执行结果:

2. Go 语言的关系运算符

Go语言中的关系运算符如表所示:

运算符结合性                         描述
==从左到右左右两边实体相等运算结果为true,否则为false
!=从左到右左右两边实体不等运算结果为true,否则为false
>=从左到右

左边的实体大于或等于右边运算结果为true

,否则为false

>从左到右左边的实体大于右边运算结果为true,否则为false
<=从左到右

左边的实体小****于或等于右边运算结果为true

,否则为false

<从左到右左边的实体小于右边运算结果为true,否则为false

代码示例:

package main

import (
"fmt"
)

func main() {
var a = -7
var b = 4

fmt.Println("a == b :", a == b)
fmt.Println("a != b :", a != b)
fmt.Println("a >= b :", a >= b)
fmt.Println(" a > b :", a > b)
fmt.Println("a <= b :", a <= b)
fmt.Println(" a < b :", a < b)
}

执行结果:

3. Go 语言的逻辑运算符

Go语言中的逻辑运算符如表所示:

运算  符

       结合性                  

                           描述
&&从左到右

左右实体均为 true 运算结果为 true 

,否则为 false

||从左到右左右实体均为 false                                                            运算结果为 false ,否则为 true
从右到左右边实体为 false 运算结果为 true ,                                            否则为 false

代码示例:

package main

import (
"fmt"
)

func main() {
var a = true
var b = false

fmt.Println("a && b :", a && b)
fmt.Println("a || b :", a || b)
fmt.Println(" !a :", !a)
}

运算结果:

4. Go 语言的位运算符

Go 语言的位运算符如表所示:

运算符结合性描述
&从左到右按位与
|从左到右按位或
^从左到右按位异或
<<从左到右左位移
>>从左到右右位移

代码示例:

package main

import (
"fmt"
)

func main() {
var a = 28 //0001 1100
var b = 99 //0110 0011

fmt.Println(" a & b :", a&b) //0 : 0000 0000
fmt.Println(" a | b :", a|b) //127 : 0111 1111
fmt.Println(" a ^ b :", a^b) //127 : 0111 1111
fmt.Println("a >> 2 :", a>>2) //7 : 0000 0111
fmt.Println("b << 1 :", b<<1) //198 : 1100 0110
}

执行结果:

5.Go 语言的赋值运算符

Go语言赋值运算符如下表所示:

运算符结合性描述
=从右到左将左边的实体赋值给右边的变量                                                              
+=从右到左

将右边的变量与左边的实体进

加运算之后赋值给右边的变量

-=从右到左

将右边的变量与左边的实体进

减****运算之后赋值给右边的变量

*=从右到左

将右边的变量与左边的实体进

乘运算之后赋值给右边的变量

/=从右到左

将右边的变量与左边的实体进

除运算之后赋值给右边的变量

%=从右到左

将右边的变量与左边的实体进

取余运算之后赋值给右边的变量

>>=从右到左

将右边的变量与左边的实体进

右位移运算之后赋值给右边的变量

<<=从右到左

将右边的变量与左边的实体进

左位移运算之后赋值给右边的变量

&=从右到左

将右边的变量与左边的实体进

与运算之后赋值给右边的变量

|=从右到左

将右边的变量与左边的实体进

或运算之后赋值给右边的变量

^=从右到左

将右边的变量与左边的实体进

异或运算之后赋值给右边的变量

代码示例:

package main

import (
"fmt"
)

func main() {
var a = 28
var b = 99
a = b
fmt.Println(" a = b :", a)
a = 28
a += b
fmt.Println(" a += b :", a)
a = 28
a -= b
fmt.Println(" a -= b :", a)
a = 28
a *= b
fmt.Println(" a *= b :", a)
a = 28
a /= 2
fmt.Println(" a /= 2 :", a)
a = 28
b %= 1
fmt.Println(" b %= 1 :", a)
a = 28
a &= b
fmt.Println(" a &= b :", a)
a = 28
a |= b
fmt.Println(" a |= b :", a)
a = 28
a ^= b
fmt.Println(" a ^= b :", a)
a = 28
a >>= 2
fmt.Println("a >>= 2 :", a)

执行结果:

6. 优先级

下表为各运算符的优先级示图,优先级从高到低

优先级类别运算符
1括号运算符()
2单目运算符!、++、–
3算数运算符*、/、%
4+、-
5位移运算符>>、<<
6关系运算符<、<=、>、>=
7==、!=
8按位与&
9按位异或^
10按位或|
11逻辑与&&
12逻辑或||
13赋值运算符

=、+=、-=、*=、/=、 %=、 >=

、 <<=、&=、^=、|=

代码示例:


package main

import (
"fmt"
)

func main() {
var a = 28
var b = 99
fmt.Println(" a + b * 2 =", a+b*2) //乘法优先级较高,先执行乘法
fmt.Println("(a + b) * 2 =", (a+b)*2) //括号优先级最高,先执行括号中的运算
}

执行结果:

7. 小结

Go 语言的运算符一般分为算数运算符关系运算符逻辑运算符位运算符以及赋值运算符四大类。在使用过程中如果记不清楚运算符的优先级,可以使用特殊的运算符——括号运算符(),其优先级最高,使用它就可以随心所欲的控制优先级了。

本文主要学习 Go 语言中的分支语句。一共要介绍的有两个,分别是 if…else 和 switch…case。他们二者在 Go 语言中都做了新的功能拓展。

Tips:其中还有一个分支语句 select…case 我们将在 Go 语言的通道中介绍。

1. if…else

在 Go 语言中 if 关键字的作用和其它大部分语言相同,是用于测试某个布尔表达式或布尔值是否为真的。若为真则执行 if 之后 {} 中的语句,否则跳过这些语句。如果存在第二个分支,则需要使用 else 关键字,还需要增加分支的话就需要使用 else if 关键字了。

示例代码:

package main

import "fmt"

func main() {
a := 10
if a > 10 {
fmt.Println("a大于10")
} else if a < 0 {
fmt.Println("a小于0")
} else {
fmt.Println("a的值是", a)
}
}
  • 第 7 行:判断 a 是否大于 10,显然不满足,代码走向下一个分支 else if。Go 语言中的 if 的条件语句不需要使用 ()

  • 第 9 行:继续判断 a 是否小于 0,显然也不满足,走向最后一个分支 else。因为 Go 语言中使用 回车符来象征语句结束,所以 esle 必须写成 }else{ 的形式,不然就识别为 if 语句结束了;

  • 第 11 行:之前的分支条件都不成立,执行最后一个分支;

  • 第 12 行:打印变量 a 的值。

输出结果:

在 Go 语言中,if 后的条件表达式,还有一种特别的写法,可以在条件表达式之前写一个赋值表达式。

if…else 的特殊用法:

package main

import "fmt"

func main() {
if a := 10; a > 10 { //赋值表达式和条件表达式之间使用;隔开
fmt.Println("a大于10")
} else {
fmt.Println("a的值是", a)
}
}

执行结果:

2. switch…case

Go 语言对 switch…case 的功能进行了扩展,它变得更加的通用。switch 之后可以什么都不带。case 也无需是一个固定值,也可以是一个布尔表达式,而且每一个 case 都是一个 独立的代码块,执行完了之后立刻跳出 switch,不需要使用 break。所以可以把 if…else 完美的改写成 switch…case 的形式。

Tips:还有一种 switch 语句叫做 type switch,我们将在学习接口时介绍它

switch…case 传统用法代码示例:

package main

import "fmt"

func main() {
a := "A"
switch a {
case "A", "a":
fmt.Println("分数区间为90~100")
case "B", "b":
fmt.Println("分数区间为70~89")
case "C", "c":
fmt.Println("分数区间为0~70")
default:
fmt.Println("错误的评分")
}
}第 7 行:和传统用法一致,去求变量 A 的值和那个 case 匹配;
  • 第 8 行:case 后面的值使用逗号隔开,用于表示匹配任意一个值;

  • 第 14 行:每一个 switch 中最多可以带一个 default。

输出结果:

switch…case Go 语言中的新用法:

package main

import "fmt"

func main() {
a := 50
switch {
case a < 60:
fmt.Println("不及格")
case a < 80:
fmt.Println("良好")
case a <= 100:
fmt.Println("优秀")
default:
fmt.Println("分数最多为100分")
}
}
  • 第 7 行:switch 后不带任何参数,直接执行第 1 个 case 的判定;

  • 第 8 行:case 后面带的是一个布尔表达式,若值为 true ,则执行其后代码块;

  • 第 14 行:default 在这里就充当 else 的角色。

输出结果:

3. 小结

本文主要学习了 Go 语言中的分支结构,其中需要注意的是在 Go 语言中的特殊写法:

  • if 的条件表达式无需使用括号;

  • if 的条件表达式之前可以跟一个赋值表达式,与条件表达式之间使用 ; 分割;

  • switch 关键字之后可以不带变量;

  • case 关键字后面可以跟布尔表达式;

  • if…else 语句中,else if 如果特别多的情况下一般建议使用 switc…case 来代替。

Go 语言的循环语句

在 Go 语言中减少了循环语句的关键字,仅有一个 for 关键字。但是并没有减少其功能,而且它更是兼容了其它语言中的while关键字的用法,甚至更强大。

1. for 循环语句

1.1 普通用法

在 Go 语言中,for 循环之后一样可以跟三个语句,单次表达式;条件表达式;末尾循环体,但是它不需要使用()来包裹这三个表达式,写法上更加的简洁。同时它也和其它语言一样,可以任意省略这三个表达式。

代码示例:

package main

import "fmt"

func main() {
for a := 0; a < 10; a++ {
fmt.Println(a)
}
}

代码块

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

省略单次表达式代码示例:

package main

import "fmt"

func main() {
a := 0
for ; a < 10; a++ {//表达式可以省略,但是;不能省略
fmt.Println(a)
}
}

代码块

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

执行结果

1.2 代替 while 的用法

在其它大部分语言中 for 循环中省略单次表达式末尾循环体其实就和其它语句中的 while 用法一致了。所以在 Go 语言中,直接使用省去单次表达式末尾循环体的 for 循环语句来代替 while 的用法,为了简便代码书写,Go 语言中 for 循环语句在省去单次表达式末尾循环体时,可以不写分号。

代码示例

package main

import "fmt"

func main() {
a := 0
for a < 10 { //和其它语言中的while(a<10)一致
fmt.Println(a)
a++
}
}

代码块

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

执行结果

2. for 语言中的break 和 continue

在我们的生产环境中,经常需要用到死循环的场景。所以在 Go 语言中新增了一个 for 关键字死循环的用法,让程序员不用写无聊的 for(;;){}do{} while(1)。同时可以使用 break 和 continue 来控制循环。

Tipsbreak 和 continue 的逻辑和语法类似,故本文只介绍break。

2.1 break跳出单层死循环

在你想要结束一个死循环的时候,只需要执行一个 break 语句即可。

代码示例

package main

import "fmt"

func main() {
a := 0
for { //死循环的写法就是省略 单次表达式;条件表达式;末尾循环体
fmt.Println(a)
a++
if a >= 10 {
break //跳出死循环
}
}
}

代码块

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

执行结果

2.2 break跳出多层死循环

在其它语言中,你很难去控制跳出循环的层数,在 Go 语言中提供了一种break LOOP的写法,可以使循环跳出到 LOOP 所在的位置。

代码示例

package main

import "fmt"

func main() {
a := 0
LOOP:
for {
for {
fmt.Println(a)
a++
if a >= 10 {
break LOOP //跳出循环至LOOP所在的层级
}
}
}
}

代码块

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

执行结果

3. 小结

本文主要介绍了 for 关键字在 Go 语言的循环中的用法:

  • for 之后的语句不需要使用()包裹;

  • break+LOOP的形式可以一次性跳出多层循环;

  • for 可以和其它语言中的 while 一样使用;

  • for{…} 的形式是一个死循环。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多