美文网首页
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