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()下面的代码")
}

 

posted @ 2022-04-25 12:26  天叔  阅读(270)  评论(0编辑  收藏  举报