美文网首页
go语言学习(4)--函数和指针

go语言学习(4)--函数和指针

作者: 神奇大叶子 | 来源:发表于2018-08-02 22:46 被阅读79次

    函数

    来写一个加减乘除吧

    func eval(a, b int, op string) int {
        switch op {
        case "+":
            return a + b
        case "-":
            return a - b
        case "*":
            return a * b
        case "/":
            return a / b
        default:
            panic("unknown operation " + op)
        }
    }
    

    函数三要素,入参 函数名 返回值
    a,b 都是 int 我就不用 a int ,b int 这么写了,变量放前面,类型放后面
    所以函数返回值也是一样,返回值放后面

    多返回值函数

    /**
    多返回值
     */
    func div(a, b int) (q, r int) {
        return a / b, a % b
    }
    

    返回值那也可以只写个 int, 但是有时候为了告诉别人你这个返回值是什么意思,可以命名一下,比如这里的 q,r 代表商和余数
    那刚刚的加减乘除就可以改写一下

    func eval(a, b int, op string) int {
        switch op {
        case "+":
            return a + b
        case "-":
            return a - b
        case "*":
            return a * b
        case "/":
            q, _ := div(a, b) // _表示占位符, 啊 go 真的很严格,不允许有无用的变量
            return q
        default:
            panic("unknown operation " + op)
        }
    }
    

    上节也说到了_代表占位符,其实很多语言比如 php,python 也是用_当占位符,go 里不允许有无用变量,所以这里不需要余数这个返回值可以用_代替
    下面说个好玩牛逼的东西

    函数式编程

    还是刚刚的功能

    func evalfunc(op func(int, int) int, a, b int) int {
        return op(a, b)
    }
    

    go里函数是一等公民,函数也可以像变量一样传递
    假如我想算 a^b

    /**
    函数式编程
     */
    func evalfunc(op func(int, int) int, a, b int) int {
        // 通过反射获取函数的指针
        p := reflect.ValueOf(op).Pointer()
        // 通过指针获取函数名
        opName := runtime.FuncForPC(p).Name()
        fmt.Printf("Calling function %s with args "+
            "(%d %d)\n", opName, a, b)
    
        return op(a, b)
    }
    
    func pow(a, b int) int {
        return int(math.Pow(float64(a), float64(b)))
    }
    
    func main() {
        fmt.Println(evalfunc(pow, 3, 4))
    }
    
    // Calling function main.pow with args (3 4)
    // 81
    

    就是这么酷炫,直接把函数传到另一个函数体里
    再看一个例子

    // 匿名函数
    fmt.Println(evalfunc(
        func(a int, b int) int {
            return int(math.Pow(float64(a), float64(b)))
        }, 3, 4))
    // Calling function main.main.func1 with args (3 4)
    // 81
    

    接着上段代码,我也可以写成匿名函数的样子,就不用特意出来定义一个函数了,比如python里的 lambda 表达式

    函数式编程现在已经很流行了,推荐学一学用一用,买不了吃亏也买不了上当的

    可变参数

    go里没有java那复杂的函数重载也没有 python 的参数默认值,因为go崇尚简洁
    但是可变参还是有的

    /**
    可变参数
     */
    func sum(num ...int) int {
        s := 0
        for _, value := range num {
            s += value
        }
        return s
    }
    fmt.Println(sum(1, 2, 3)) // 6
    

    range 后面再讲,也是用的非常多的一种用法,...代表不定参,好像 js也有这种写法,其实现在很多语言都是互相借鉴,所以还是非常推荐大家学go的,语言简洁,性能非常高,又没有历史包袱

    值传递 or 引用传递

    复习一下指针的知识吧

    func passByVal(a int){
        a++
    }
    func passByRef(a *int)  {
        *a++
    }
    func main() {
        a := 3
        passByVal(a)
        fmt.Println(a)
        passByRef(&a)
        fmt.Println(a)
    }
    

    这段代码会打印什么呢
    没错
    就是3,4
    在看一个例子

    func swap(a, b *int) {
        *a, *b = *b, *a
    }
    func main(){
        b := 3
        c := 4
        swap(&b, &c)
        fmt.Println(b, c) // 4,3
    }
    

    其他的语言学习的时候可能要分值传递,引用传递,新手在这上面很容易出错.
    记住了go
    只有值传递,不论传值还是传指针他都是拷贝一份到函数体里
    指针和函数是重点,现在只是回顾一下,后面还会讲到

    总结

    总结一下吧

    • go函数返回值写在最后面,你会发现很多新的语言都是这么设计的
    • 函数可以有多个返回值
    • 函数可以作为参数传给另一个函数
    • 没有默认参数和可选参数
    • go都是值传递没有引用传递

    上述代码均已上传至 github, 欢迎 star
    https://github.com/yejunyu/golearn


    image

    相关文章

      网友评论

          本文标题:go语言学习(4)--函数和指针

          本文链接:https://www.haomeiwen.com/subject/zzrevftx.html