Go学习——4.函数

本文介绍了Go语言中函数的可变参数和切片参数的使用,强调了可变参数的优势,如简化代码开发和提高可读性。通过示例展示了如何传递可变参数,以及在传递切片给可变参数时应注意的细节,包括传递的实际上是值(即切片的地址)。最后,通过实例解释了传递切片给函数时的值传递特性及其可能带来的影响。
摘要由CSDN通过智能技术生成

函数

  1. 函数返回值有命名,可以使用返回值命名做运算,并且返回时,只需要写一个return即可
func rectProps(length, width float64)(area, perimeter float64) {
    area = length * width
    perimeter = (length + width) * 2
    return //no explicit return value
}

可变参数函数

  1. 注意点:
  • 形式:func fname(a int, b … int){} 这的b就是可变参数,其实就是在类型前面加 …
  • 只有函数的最后一个参数可以是可变的
  • 可变参数的类型是切片 比如[]int,
  • 如果可变参数没有实参,那么就是默认值,也就是切片的默认值,nil slice,其长度和容量都是0。
  package main

  import (
      "fmt"
  )

  func find(num int, nums ...int) {
      fmt.Printf("type of nums is %T\n", nums)
      found := false
      for i, v := range nums {
          if v == num {
              fmt.Println(num, "found at index", i, "in", nums)
              found = true
          }
      }
      if !found {
          fmt.Println(num, "not found in ", nums)
      }
      fmt.Printf("\n")
  }
  func main() {
      find(89, 89, 90, 95)
      find(45, 56, 67, 45, 90, 109)
      find(78, 38, 56, 98)
      find(87)
  }
  1. 可变参数与切片参数的区别

既然可变参数本身就会被转换成一个切片,接收不定个数的元素,那为何不直接用切片,切片也是可以满足任意个数元素的??

package main

import (
    "fmt"
)

func find(num int, nums []int) {
    fmt.Printf("type of nums is %T\n", nums)
    found := false
    for i, v := range nums {
        if v == num {
            fmt.Println(num, "found at index", i, "in", nums)
            found = true
        }
    }
    if !found {
        fmt.Println(num, "not found in ", nums)
    }
    fmt.Printf("\n")
}
func main() {
    find(89, []int{89, 90, 95})
    find(45, []int{56, 67, 45, 90, 109})
    find(78, []int{38, 56, 98})
    find(87, []int{})
}
  • 上面这段代码,与再上面的一段代码对比,我们可以得出可变参数的一些优势:
    • 减少了每次函数调用都需要创建slice的麻烦,每次的函数调用,我们都需要创建一个新的slice。而使用可变参数函数就可以避免slice的创建,从而简化代码的开发。
    • 在上一个程序的最后一行即:find(87, []int{}),我们创建了一个空数组,就是为了满足find的函数定义。这在可变参数函数中完全是不必的。当使用可变参数函数时,我们只需要写个find(87)就行了。
    • 使用可变参数的程序相对于使用slice的程序来说,可读性更强。

Append是一个可变参数函数

当使用append函数向一个slice中追加值时,为什么append函数可以接收任意数目的实参。这是因为,append函数其实是一个可变函数:

func append(slice []Type, elems ...Type) []Type

传递slice给可变参数函数

我们知道可变参数是一个切片slice,那么如果我们再传一个切片进去,可以吗?(答案:不可以)

func find(num int, nums ...int) {

}

func main() {
    nums := []int{89, 90, 95}
    find(89, nums) // 报错:cannot use nums (type []int) as type int in argument to find。
}
  • 那么有没有办法传递slice给可变参数呢?
    • 有的,用语法糖,在实参后面加上…
func find(num int, nums ...int) {

}

func main() {
    nums := []int{89, 90, 95}
    find(89, nums...) // 编译通过
}

传递slice给可变参数函数传的是地址

package main

import (
    "fmt"
)

func change(s ...string) {
    s[0] = "Go"
}

func main() {
    welcome := []string{"hello", "world"}
    change(welcome...)
    fmt.Println(welcome) // 结果是[]string {"Go", "world"} 
}
  • 可以看出,函数传递的都是值,只不过这里把地址作为值传入,所以里面改变,外面也会跟着改变
  • 再来看个易错的例子:
package main

import (
    "fmt"
)

func change(s ...string) {
    s[0] = "Go"
    s = append(s, "playground")
    fmt.Println(s) // 打印出 [Go world playground]
}

func main() {
    welcome := []string{"hello", "world"}
    change(welcome...)
    fmt.Println(welcome) // 打印出 [Go world]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值