【GoWeb编程笔记】第1章 Go基础入门 -2

4. switch-case语句

Go语言中的switch-case语句要比C语言的switch-case语句更加通用,表达式的值不必为常量,甚至不必为证书。case按照从上往下的顺序进行求值,直到找到匹配的项。可以将多个if-else语句改写成一个switch-case语句。Go语言中的switch-case语句使用比较灵活,语法设计以使用方便为主。

Go语言改进了传统的switch-case语句的语法设计:casecase之间是独立的代码块,不需要通过break语句跳出当前case代码块,以避免执行到下一行。示例代码如下。

var a = "love"
switch a {
	case "love":
		fmt.Println("love")
	case "programming":
		fmt.Println("programming")
	default:
		fmt.Println("none")
}

以上代码的运行结果如下:

love

在上面例子中,每一个case都是字符串格式,且使用了default分支。Go语言规定每个switch只能有一个default分支。

同时,Go语言还支持一些新的写法,比如一个分支多个值、分支表达式。

(1)一个分支多个值。

当需要将多个case放在一起时,可以写成下面这样:

var language = "golang"
switch language{
	case "golang", "java":
		fmt.Println("popular languages")
}

以上代码的运行结果如下:

popular languages

在一个分支多个值的case表达式中,使用逗号分隔值。

(2)分支表达式

case语句即可以是常量,也可以和if一样添加表达式。示例如下:

var r int = 6
switch {
	case r > 1 && r < 10:
		fmt.Println(r)
}

在这种情况下,switch后面不再需要添加用于判断的变量。

5. goto语句

在Go语言中,可以通过 goto语句跳转到标签,进行代码间的无条件跳转。另外,goto语句在快速跳出循环、避免重复退出方面也有一定的帮助。使用goto语句能简化一些代码的实现过程。

在满足条件时,如果需要连续退出两层循环,则传统的编码方式如下:

func main(){
	var isBreak bool
	for x := 0; x < 20; x++{
		for y := 0; y < 20; y++{
			if y == 2{
				isBreak = true
				break
			}
		}
		if isBreak{
			break
		}
	}
	fmt.Println("over")
}

将上面的代码使用Go语言的goto语句进行优化:

func main(){
	for x := 0; x < 20; x++{
		for y := 0; y < 20; y++{
			if y == 2{
				goto breakTag
			}
		}
	}
	return
	breakTag:
		fmt.Println("done")
}

在以上代码中,使用goto语句goto breakTag来跳转到指明的标签处。breakTag是自定义的标签。

在日常开发中,经常会遇到“多错误处理”问题,在“多错误处理”中往往存在代码重复的问题。例如:

func main(){
	// 省略前面代码
	err := getUserInfo()
	if err != nil {
		fmt.Println(err)
		exitProcess()
		return
	}
	err := getEmail()
	if err != nil {
		fmt.Println(err)
		exitProcess()
		return
	}
	fmt.Println("over")
}

在上面代码中,有一部分是重复的代码。如果后期需要在这些代码中添加更多的判断条件,则需要在这些雷同的代码中重复修改,极易造成疏忽和错误。这时可以通过使用goto语句来处理:

func main(){
	// 省略前面代码
	err := getUserInfo()
	if err != nil {
		goto doExit
	}
	err := getEmail()
	if err != nil {
		goto doExit
	}
	fmt.Println("over")
	return
doExit:
	fmt.Println(err)
	exitProcess()
}
6. break语句

Go语言中的break语句可以结束forswitchselect的代码块。另外,还可以在break语句后面添加标签,表示退出标签对应的代码块。添加的标签必须定义在对应的forswitchselect的代码块上。

通过指定标签跳出循环的示例如下。

代码 chapter1/1.3-break.go 通过指定标签跳出循环

package main

import "fmt"

func main(){
OuterLoop:
	for i := 0; i < 2; i++{
		for j:=0; j < 5; j++{
			switch j {  // 用switch 进行数值分支判断
				case 1:
					fmt.Println(i, j)
					break OuterLoop
				case 2:
					fmt.Println(i, j)
					break OuterLoop
			}
		}
	}
}

以上代码的运行结果如下:

0 1
7. continue语句

在Go语言中,continue语句用于结束当前循环,并开始下一次的循环迭代过程。它仅限在for循环内使用。在continue语句后添加标签,表示结束标签对应语句的当前循环,并开启下一次的外层循环。continue语句的使用示例如下。

代码 chapter1/1.3-continue.go continue语句的使用示例

package main

import "fmt"

func main(){
OuterLoop:
	for i:=0; i<2; i++{
		for j:=0; j<5; j++{
			switch j {
				case 3:
					fmt.Println(i, j)
					continue OuterLoop
			}
		}
	}
}

以上代码的运行结果如下:

0 3
1 3

1.4 Go数据类型

Go语言的基本数据类型分为布尔型、数学类型、字符串类型、复合类型这4种。其中复合类型又分为:数组类型、切片类型、Map类型、结构体类型。Go语言常见基本数据类型如下:

类型说明
布尔型布尔型的值只可以是常量true或者false。一个简单的例子:var b bool = true
数字类型包含uint8 uint16 unint32 uint64 int8 int16 int32 int64 float32 float64 complex64 complex128 byte rune unit int uintptr(无符号整型,用于存放一个指针)
字符串类型字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本
复合类型包含数组类型、切片类型、Map类型、结构体类型

1.4.1 布尔型

布尔型的值只可以是常量true或者falseiffor语句的条件部分都是布尔类型的值,并且==<等比较操作也会产生布尔型的值。

一元操作赴(!)对应逻辑“非”操作,因此!true的值为false。更复杂的写法是(!true==false)==true。在实际开发种,应尽量采用比较简洁的布尔表达式。

var aVar = 100
fmt.Println(aVar == 50)
fmt.Println(aVar == 100)
fmt.Println(aVar != 50)
fmt.Println(aVar != 100)

布尔值可以和&&(AND)||(OR)操作符结合。如果运算符左边的值已经可以确定整个布尔值表达式的值,则运算符右边的值将不再被求值,因此下面的表达式是安全的:

str1 == "java" && str2 == "golang"

布尔值并不会隐式转化为数字值0或1,反之亦然,必须使用if语句显式地进行转换:

i := 0
b := true
if b {
    i = 1
}

如果需要经常做类似的转换,则可以将转换的代码封装成一个函数,如下所示:

// 如果b为真,则boolToInt()函数返回1;如果为假,则boolToInt()函数返回0
// 将布尔型转换为整型
func boolToInt(b bool) int {
    if b {
        return 1
    }
    return 0
}

1.4.2 数字类型

Go语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码。

Go语言也有基于架构的类型,例如:intuintuintptr。这些类型的长度都是根据运行程序所在操作系统类型所决定。

1.4.3 字符串类型

字符串是由一串固定长度的字符连接起来的字符序列。Go语言种的字符串是由单个字节连接起来的。Go语言种的字符串的字节使用UTF-8编码来便是Unicode文本。UTF-8是一种被广泛使用的编码格式,是文本文件的标准编码。包括XMLJSON在内都使用该编码。

由于该编码占用字节长度的不定性,所以在Go语言种,字符串也可能根据需要占用1~4byte

字符串是一种值类型。更深入地讲,字符串是字节的定长数组。

1. 字符串的声明和初始化

声明和初始化字符串非常容易:

str := "hello string!"

上面的代码声明了字符串变量str,其内容为“hello string!”。

2. 字符串的转义

在Go语言中,字符串字面量使用英文双引号(")或者反引号(`)来创建。

  • 双引号用来创建可解析的字符串,支持转义,但不能用来引用多行;
  • 反引号用来创建原生的字符串字面量,可能由多行组成,但不支持转义,并且可以包含除反引号外的其他所有字符。

用双引号来创建可解析的字符串应用很广泛,用反引号来创建原生的字符串则多用于书写多行消息、HTML及正则表达式。

使用示例如下:

str1 := "\"Go Web\", I love you \n"  // 支持转义,但不能用来引用多行
str2 := `Go Web,
I love you \n`  // 支持多行组成,但不支持转义
println(str1)
println(str2)

以上代码的运行结果如下:

"Go Web", I love you

"Go Web",
I love you

3. 字符串的连接

虽然Go语言中的字符串是不可变的,但是字符串支持级联操作(+)和追加操作(+=),比如下面这个例子:

str := "I love" + " Go Web"
str += " programming"
fmt.Println(str)   // I love Go Web programming
4. 字符串的操作符

字符串的内容(纯字节)可以通过标准索引法来获取:在方括号[]内加入索引,索引从0开始计数。

假设我们定义了一个字符串str := "programming",则可以通过str[0]来获取字符串str的第1个字节,通过str[i-1]来获取第i个字节,通过str[len(str)-1]来获取最后一个字节。

通过下面具体的示例,可以理解字符串的常用方法:

str := "programming"
fmt.Println(str[1])   // 获取字符串索引位置为1的原始字节,比如r为114
fmt.Println(str[1:3])  // 截取字符串索引位置为1和2的字符串(不包含最后一个)
fmt.Println(str[1:])   // 截取字符串索引位置为1到len(s)-1的字符串
fmt.Println(str[:3])   // 截取字符串索引位置为0到2的字符串(不包含3)
fmt.Println(len(str))  // 获取字符串的字节数
fmt.Println(utf8.RuneCountInString(str))  // 获取字符串字符的个数
fmt.Println([]rune(str))  // 将字符串的每一个字节转换为码点数
fmt.Println(string(str[1]))  // 获取字符串索引位置为1的字符值

以上代码的运行结果如下:

114
ro
rogramming
pro
11
11
[112 114 111 103 114 97 109 109 105 110 103]
r
5. 字符串的比较

Go语言中的字符串支持常规的比较操作(<>==!=<=>=),这些操作符会在内存中一个字节一个字节地进行比较,因此比较的结果是字符串自然编码的顺序。

6. 字符串的遍历

通常情况下,可以通过索引提取其字符,比如:

str := "go web"
fmt.Println(string(str[0]))  // 获取索引为0的字符

以上的字符串是单字节的,通过索引可以直接提取字符。但是对于任意字符串来讲,上面并不一定可靠,因为有些字符可能有多个字节。这时就需要使用字符串切片,这样返回的将是一个字符,而不是一个字节:

str := " i love go web"
chars := []rune(str)  // 把字符串转为rune切片
for _,char := range chars{
    fmt.Println(string(char))
}

在Go语言中,可以用rune或者int32来表示一个字符。

字符可以通过+=操作符在一个循环中往字符串末尾追加字符。但这并不是最有效的方式,还可以使用类似Java中的StringBuilder来实现。

var buffer bytes.Buffer  // 创建一个空的bytes.Buffer
for {
    if piece,ok := getNextString();ok{
        // 通过WriteString()方法,将需要串联的字符串写入buffer中
        buffer.WriteString(piece)
    } else{
        break
    }
}
fmt.Println(buffer.String())  // 用于取回整个级联的字符串

如果要将字符串一个字符一个字符地迭代出来,则可以通过for-range循环:

str := "love go web"
for index, char:= range str{
    fmt.Printf("%d %U %c \n", index, char, char)
}
7. 字符串的修改

在Go语言中,不能直接修改字符串的内容,即不能通过str[i]这种方式修改字符串中的字符。如果要修改字符串的内容,则需要先将字符串的内容复制到一个可写的变量中(一般是[]byte[]rune类型的变量),然后再进行修改。在转换类型的过程中会自动复制数据。

(1)修改字节(用[]byte)。

对于单字节字符,可以通过这种方式进行修改:

str := "Hi 世界!"
by := []byte(str)   // 转换为[]byte, 数据被自动复制
by[2] = ','
fmt.Printf("%s\n", str)
fmt.Printf("%s\n", by)

(2)修改字符(用[]rune)。

str := "Hi 世界!"
by := []rune(str)   // 转换为[]rune, 数据被自动复制
by[3] = '中'
by[4] = '国'
fmt.Println(str)
fmt.Println(string(by))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值