Go语言中的函数_2021_11_01

  函数的定义和 函数的调用

package main

import "fmt"

func main() {
    sayHelloWorld()
    fmt.Printf("%T \n", sayHelloWorld) // func() ,是一个函数

    sayHi("张三") // 你好 张三 ,实参

    fmt.Println(add(1,5))                   // 6

}



// 定义一个函数
// 参数
// 返回值
func   bublo_sort(heights []int) {
    //先把最高的人排到最后
    for i := 0; i < len(heights); i++ {
        for j := i + 1; j < len(heights); j++ {
            if heights[i] > heights[j] {
                heights[i], heights[j] = heights[j], heights[i]
            }
        }
    }

}

//定义函数 ,定义一个无参,无返回值的函数
func sayHelloWorld() {
    fmt.Println("hello world!")
}

func sayHi(name string) { //形参
    fmt.Println("你好 " + name)
}

func add (a int ,b int ) int {
    return a + b
}

函数的定义及使用

package main

import "fmt"

func main() {

    a, b, c, d := calc1(1, 2)
    fmt.Println(a, b, c, d)

    sum, sub, mul, div := calc2(2, 1) //3 1 2 2
    fmt.Println(sum, sub, mul, div)
}

//函数的返回值有多可,可以用多个变量去接收到
func calc1(a, b int) (int, int, int, int) {
    return 1, 2, 3, 4
}

func calc2(a, b int) (sum int, sub int, mul int, div int) {
    sum = a + b
    sub = a - b
    mul = a * b
    div = a / b
    return
}

函数的递归

package main

import "fmt"

func main() {
    fmt.Println(sumx(100))
    //
    fmt.Println(mulx(9)) // 324

    tower("A","B","C",3)
}
// 递归 100 + ... + 1
func sumx(index int) int {
    if index <= 1 {
        return 1
    }
    return index + sumx(index-1)
}
// n !
func mulx(index int) int {
    if index <= 1 {
        return 1
    }
    return index * sumx(index-1)
}



// 1个盘子 1 -C             1
// 2个盘子 1 -> B ,2 -> C ,1 -> C   3
// 3个盘子 1->C 2->B ,1 -> B , 3 -> C , 1-> A ,2 -> C ,1 -> C   7  ,
// 4个盘子 1 -> B , 2 -> C , 1 -> C , 3 -> B , 1 - > A , 2 -> B ,1 -> B , 4 -> C , 1 -> C , 2 -> A ,1 -> A , 2 -> C , 1 -> B , 2 -> C , 1 -> C  , 15
// 汉诺塔游戏
func tower(a, b, c string, lay int) {
    if lay == 1 {
        fmt.Println(a, "->", c)
        return
    }
    tower(a,c,b,lay-1)
    fmt.Println(a ,"->",c)
    tower(b,a,c,lay -1 )
}
匿名函数
package main

import "fmt"

func main() {
    fmt.Printf("%T\n", fsum) // func(int, int) int
    var f func(int, int) int = fsum
    fmt.Println(f(1, 2))
    printx(list, "1", "2", "3") // 1       2       3


    // 定义一个匿名函数
    sayHello1 := func (name string) {
        fmt.Println("hello ", name)
    }
    sayHello1("kka")

    //匿名函数只调用一次的情况下使用
    func (name string){                 // hahah
        fmt.Println(name)
    }("hahah")

    values := func(args ...string) {
        for _,v := range  args {
            fmt.Println(v)
        }
    }

    printx(values,"A","B","C")
}


func fsum(a, b int) int {
    return a + b
}

// callback格式 ,将传递的数据按照每行打印 还是按照一行一行打印
func printx(callback func(...string), args ...string) {
    fmt.Println("print函数的输出 :")
    callback(args...)



}


func list(args ...string) {
    for _, v := range args {
        fmt.Printf("%s \t", v)
    }
}

闭包
package main

import (
    "fmt"
)

func main() {
    add2 := func(n int) int {
        return n + 2
    }
    fmt.Println(add2(2))

    add10 := func(n int) int {
        return n + 10
    }
    fmt.Println(add10(10))

    // 闭包问题
    addbase := func(base int) func(int) int {
        // 返回一个函数
        return func(n int) int {
            return base + n
        }
    }
    fmt.Println(addbase(8)(10)) // 18
    fmt.Printf("%T \n",addbase(8))          // 返回一个函数
    add4 := addbase(4)
    add8 := addbase(8)
    add11 := addbase(11)
    
    fmt.Println(add4(4))                    //8
    fmt.Println(add8(4))                        // 12
    fmt.Println(add11(4))//15
}


7.值类型与引用类型和值传递

  在Go语言中参数传递默认均以值传递(形参为实参变量的副本),对于引用类型的数据因为其底层共享数据结构,所以在函数的内可以引用类型数据修改从而影响函数外的原来变量的信息。

package main

import "fmt"

func main() {
    array:= [3]string{"A","B","C"}
    slice := []string{"A","B","C"}


    arrayA := array
    sliceA := slice

    arrayA[0] = "D"
    sliceA[0] = "D"
    fmt.Println(array ,arrayA == array)             //值类型
    //值类型,引用类型
    // 将变量赋值给新的一个变量,如果对变量有影响,引用类型,如果对变量没有影响,就是值类型
    fmt.Println(slice)


    // int ,bool,float32 ,float64 ,array ,slice ,map
    //  int ,bool,float32 ,float64 ,array,结构体 值类型
    // slice ,map ,接口,引用类型
    // 指针是一个值类型
    m := map[string]string{}
    mA := m
    mA["kk"] = "张天"
    fmt.Println(m) // map[kk:张天]

    //通过指针来改值
    age :=30
    b := &age
    *b = 20
    fmt.Println(age,*b)


    fmt.Printf("%p %p \n", & age ,& b )// 0xc0000b2020 0xc0000ac020
    fmt.Printf("%p %p \n", slice ,sliceA )  // 0xc000098180 0xc000098180
    fmt.Printf("%p %p \n", & slice[0] ,& sliceA[0] )// 0xc000098180 0xc000098180
    fmt.Printf("%p %p \n", & array,&arrayA )    // 0xc00006e180 0xc00006e1e0


}

针对值类型和引用类型在赋值后新旧值的地址并不相同,只是引用类型在底层的共享数据结构(其中包含指针类型的元素 )

值类型数据结构 :
在这里插入图片描述
引用类型数据结构:
在这里插入图片描述

package main

import "fmt"

func changeInt(a int) {
    a = 100
}

func changeSlice(s []int) {
    s[0] = 100
}

func changeIntAddress(n *int) {
    *n = 2

}

// 修改地址的地址对应的值
func changeIntAddressAddresss(n **int) {
    **n = 10
}

func main() {

    num := 1
    changeInt(num)
    fmt.Println(num) // 1  ,按值传递,是不会修改外面的值

    nums := []int{1, 2, 3}
    changeSlice(nums)
    fmt.Println(nums) // [100 2 3]       ,引用类型的数据是会修改外面的数据的

    changeIntAddress(&num)
    fmt.Println(num)                    // 2

    num2 := &num
    changeIntAddressAddresss(&num2)
    fmt.Println(num)                            // 10
}
错误处理

需要自己处理错误信息

package main

import (
    "errors"
    "fmt"
)

func div(a, b int) (int, error) {
    if b == 0 {
        return -1, errors.New("div by zero")
    }
    return a / b, nil
}

//返回值,怎样定义错误类型
// 怎么创建错误类型对应的值信息
func main() {
    //num := 1 / 0
    //fmt.Println(num) // ./error1.go:6:11: division by zero
    fmt.Println(div(1, 0))

    e := fmt.Errorf("error %s ","div by zero")
    fmt.Printf("%T  ,%v \n",e ,e)                   // *errors.errorString  ,error div by zero

}
延迟执行

defer关键字用户声明函数,不论函数是否发生错误都在函数执行最后执行(return) 若使用defer声明多个函数,则按照声明的顺序,先声明执行(堆)常用来做资源释放,记录日志等工作
常用来做资源释放,记录日志的工作

panic 和recover函数
go语言提供了panic和recover函数用于处理运行时错误,当调用panic抛出错误,中断 有的控制流程,常用于不可以修复的错误,recover函数用于终止错误处理流程,仅在defer语句的函数中有效,用于截取处理流程,recover只能捕获最后一个错误处理
panic

package main

import "fmt"

func main() {

    // 当函数退出的时候执行
    defer func() {
        fmt.Println("defer2")
    }()

    defer func() {
        fmt.Println("defer2")
    }()

    fmt.Println("main over ")
    //main over
    //xxx
}

异常处理:

package main

import (
    "fmt"
)

func testxx() (err error) {
    defer func() {
        if e := recover(); e != nil {
            err = fmt.Errorf("%v", e)
        }
    }()
    panic("error___________________")
}
func main() {
    err := testxx()
    fmt.Println(err)
    /*defer func() {
        fmt.Println()
        if err := recover(); err != nil {
            fmt.Println(err)
            fmt.Println("恢复处理")

        }
    }()
    fmt.Println("main start ")

    panic("error xxx")
    fmt.Println("over")
*/
}

命令行用户管理
用户信息存储
=> 内存 [] map
=>存储结构 id name age tel addr [len] [] map 值类型都用string类型
用户添加
用户删除
用户查询

package main

import (
    "fmt"
    "os"
    "strconv"
    "strings"
)

//添加用户
func addx(users map[string]map[string]string) {
start:
    var (
        id   string
        name string
    )
    fmt.Println("请输入姓名或退出(q/Q):")
    fmt.Scan(&name)
    if name == "q" || name == "Q" {
        return
    }
    id = getmaxId(users)
    users[id] = map[string]string{
        "id":   id,
        "name": name,
    }
    fmt.Println(users)
    goto start

}

func getmaxId(users map[string]map[string]string) string {
    maxId := 1
    for k, _ := range users {
        if i, err := strconv.Atoi(k); err == nil {
            if maxId < i {
                maxId = i
            }
        }
    }
    maxId = maxId + 1
    return strconv.Itoa(maxId)
}

func inputString(prompt string) string {
    fmt.Println(prompt)
    var inputId string
    fmt.Scan(&inputId)
    return strings.Trim(inputId, " ")
}

//更新用户
func updatex(users map[string]map[string]string) {
    fmt.Println("请输入要修改用户姓名:")
    var inputId string
    fmt.Scan(&inputId)
    xx := strings.Split(inputId, "_")
    fmt.Println(xx)
    for k, v := range users {
        for _, name := range v {
            if strings.Contains(name, xx[0]) {
                users[k]["name"] = xx[1]
                break
            }
        }
    }
}

//删除用户
func deletex(users map[string]map[string]string) {
start:
    fmt.Println("请删除用户姓名:")
    var inputId string
    fmt.Scan(&inputId)
    if inputId == "q" || inputId == "Q" {
        return
    }
    if inputId == "all" {
        for k, _ := range users {
            delete(users, k)
        }
    } else {
        for k, v := range users {
            for _, name := range v {
                if strings.Contains(name, inputId) {
                    delete(users, k)
                    break
                }
            }
        }
    }
    goto start
}

//
func queryx(users map[string]map[string]string) {
start:
    fmt.Println("请输入要查询的用户姓名或退出(q/Q):")
    var inputId string
    fmt.Scan(&inputId)
    if inputId == "q" || inputId == "Q" {
        return
    }
    if inputId == "all" {
        for _, v := range users {
            fmt.Printf("%5s|%20s\n", v["id"], v["name"])
        }
    } else {
        for _, v := range users {
            for _, name := range v {
                if strings.Contains(name, inputId) {
                    fmt.Printf("%5s|%20s\n", v["id"], v["name"])
                    break
                }
            }
        }
    }
    goto start
}

const (
    maxAuth  = 3
    password = "132"
)

// 从命令行中输入值
func auth() bool {
    var input string
    fmt.Println("请输入密码:")
    for i := 0; i < maxAuth; i++ {
        fmt.Scan(&input)
        if input == password {
            return true
        } else {
            fmt.Println("你的密码错误,请重新输入:")
        }
    }
    return false
}

func main() {
    if !auth() {
        fmt.Println("你的密码错误")
        return
    }
    callbacks := map[string]func(map[string]map[string]string){
        "1": addx,
        "2": updatex,
        "3": deletex,
        "4": queryx,
    }
    fmt.Println(callbacks)
    //存储用户信息
    users := make(map[string]map[string]string)
    fmt.Println("欢迎使用用户管理系统:")
    //id := 0
    for {
        var op string
        fmt.Println(`请输入指令:
1.新建用户 2.修改用户 3.删除用户 4.查询用户 q.退出`)
        fmt.Scan(&op)
        if "q" == op {
            //return
            os.Exit(500)                        //直接退出
        }

        callbacks[op](users)
        /*switch op {
        case "1":
            id++
            addx(&id, users)
            break
        case "2":
            updatex(users)
            break
        case "3":
            deletex(users)
            break
        case "4":
            queryx(users)
            break
        case "q":
            return
        default:
            break
        }*/
    }
}

github地址是

https://github.com/quyixiao/go_learn.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值