Golang第三章:switch、循环、函数、包、错误处理
switch
switch匹配项后不需要加break
case后多表达式
var score int = 80 var score2 int = 90 var score3 int = 100 // 结果输出1,score判断是否等于score2后会再判断是否等于80 switch score { case score2, 80: fmt.Println("1") case score3: fmt.Println("2") default: fmt.Println("no") }
fallthrough穿透
var score int = 80 var score2 int = 90 var score3 int = 100 switch score { case score2, 80: fmt.Println("1") fallthrough // 默认只能穿透1层,结果会输出1和2 case score3: fmt.Println("2") default: fmt.Println("no") }
循环
for的几种写法
// for循环第一种写法 for i := 1; i < 10; i++ { fmt.Println(i) } // for循环第二种写法 num := 1 for num < 10 { fmt.Println("num:", num) num++ } // for循环第三种写法 num2 := 1 for { if num2 < 10 { fmt.Println("num2:", num2) num2++ }else { break } }
for循环遍历字符串
// 方法一——传统方法,按字节遍历,不切片遇中文会乱码 var str string = "hahahaha,北京" str2 := []rune(str) // 切片操作 for i:=0; i < len(str2);i++ { fmt.Printf("i=%d val=%c\n", i, str2[i]) } // 方法二,使用字符方式遍历,可正确输出中文 str = "12312f,北京" for index, val := range str { fmt.Printf("i=%d val=%c\n", index, val) }
函数
函数定义
package main import "fmt" func cal(n1 float64, n2 float64, operator byte) (float64) { var res float64 switch operator { case '+': res = n2 + n1 case '-': res = n2 - n1 default: res = 0 fmt.Println("error") } return res } func main() { var f1 float64 = 5.12 var f2 float64 = 2.52 var f3 float64 = cal(f1, f2, '+') fmt.Println(f3) }
注意点
1. 基本数据类型和数组都是值传递的,在函数内修改不会影响原来的值
2. 如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量
3. 函数不支持重载
4. 函数也是一种数据类型,可以赋值给一个变量,通过该变量可以对函数调用
init函数
每个源文件都可以包含一个init函数,该函数会在main函数执行前被调用;如果一个文件同时包含全局变量定义,init函数和main函数,执行顺序为全局变量定义->init函数->main函数。
main.go调用utils.go的执行顺序
匿名函数
如果我们只希望某个函数执行一次,可以考虑使用匿名函数,匿名函数也支持多次调用
var ( Fun1 = func(n1 int , n2 int) int { return n1 * n2 } ) func main() { //在定义匿名函数时就直接调用,这种方式匿名函数只能调用一次 res1 := func(n1 int, n2 int) int { return n1 + n2 }(10, 20) fmt.Println(res1) //30 //将匿名函数赋值给res2,res2的数据类型就是函数类型 res2 := func(n1 int, n2 int) int { return n1 - n2 } a := res2(20, 10) fmt.Println(a) //10 res3 := Fun1(10, 20) fmt.Println(res3) //200 }
内置函数
new:用来分配内存,主要用来分配值类型,比如int、float32、struct返回的是指针
make:用来分配内存,主要用来分配引用类型,比如chan、map、slice
闭包
闭包就是一个函数和与其相关的引用环境组合的一个整体
如上图返回的结果是一个匿名函数,但是这个匿名函数引用到函数外的变量,因此该匿名函数和外部引用到的变量形成一个整体,构成闭包。
当我们反复调用f函数时,因为外部变量只会初始化一次,因此返回的结果就是累加后的值
包
包的编译
如果要编译成一个可执行文件,就需要将这个包声明为main,即package main;如果是写一个库,包名可以自定义
包的调用
在cmd命令下执行:go env -w GO111MODULE=off——选择无模块支持,让go从 GOPATH 和 vendor 文件夹寻找包
之后配置好GOPATH,本地配置为
文件目录如下
要调用的包的函数名的首字符需要大写,对应Java等语言的public,如下方的func Make()
// chapter1/main.go
package main
import(
"fmt"
"go_code/src/project01/chapter1/other"
)
func main(){
fmt.Println("主包")
other.Make()
}
// chapter1/other/main.go
package other
import (
"fmt"
)
func Make() {
fmt.Println("调用的")
}
最后我们进到chapter1目录下,执行go run main.go,得出以下结果,则自定义导包成功
包的别名
设置了包的别名后,再要调用该包就必须使用别名,如下图用原来的utils则会报错
错误处理
func test() { // 使用defer + recover来捕获和处理异常 defer func() { err := recover() // recover()内置函数,可以捕获异常 if err != nil { fmt.Println("err=", err) } }() num1 := 30 num2 := 0 res := num1 / num2 fmt.Println("res=", res) } func main() { // 测试 test() fmt.Println("main()下面的代码") }