linuxea:go有参可变函数-返回值(31)


函数对代码进行复用。这和定义一个函数类似,不同的是是对代码块起一个名字,并且可以定义一些参数,这些参数可以进行传递和接收后进行处理 ,处理的结果也需要返回。可见,函数定义有:函数名函数体函数参数返回值

I. 1.函数

  • go没有默认值,go的函数传递是非常简单,安装参数位置进行传递。

其中,参数和返回值是可以有,也可以没有的。

如果代码形式就成了下面这样

func 函数名(函数参数) (返回值) {}

函数参数(行参),是函数快的局部变量。行参返回值都需要描述参数类型和返回值的类型。

  • 如果行参配置后,也必须传入相应的值

此前,使用的 fnuc main也是函数

func main(){}

函数也可以赋值给变量,存储在数组,切片,映射中,也可以作为参数传递给函数或作为函数返回值进行返回。函数的参数,数量,对应类型,以及函数返回值称为函数的签名。

II. 1.1无参数无返回值函数

现在,简单写一个hello world.

package main
import "fmt"
func sayHello(){
    fmt.Println("Hello world!")
}

而后在main函数中调用,并打印类型

func main(){
    fmt.Printf("%T",sayHello)
    sayHello()
}

代码块

package main
import "fmt"
func sayHello(){
    fmt.Println("Hello world!")
}
func main(){
    fmt.Printf("%T",sayHello)
    sayHello()
}

运行

[root@LinuxEA /opt/Golang/work3]# go run func.go
func()Hello world!
Hello world!

在main函数中可以调用多次sayHello函数

package main
import "fmt"
func sayHello(){
    fmt.Println("Hello world!")
}
func main(){
    fmt.Printf("%T",sayHello)
    sayHello()
    sayHello()
    sayHello()
    sayHello()
    sayHello()
}

运行

[root@LinuxEA /opt/Golang/work3]# go run func.go
func()Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!

III. 1.2有参数无返回值函数

如上,在sayHello中加上参数name string。这里的参数也可以称为行参

如果设置了多少个行参,也必须传入多个。

func sayHello(name string){
    fmt.Printf("Hello %s!",name)
}

name string是字符串类型,调用的时候也需要传入字符串.

这里传入的是"mark"sayHello,打印的时候打印的name就是mark。main函数中传递的参数也可以称为实参

func main(){
    sayHello("mark")
}

代码块

[root@LinuxEA /opt/Golang/work3]# cat func2.go
package main
import "fmt"
func sayHello(name string){
    fmt.Printf("Hello %s!",name)
}
func main(){
    sayHello("mark")
}

运行

[root@LinuxEA /opt/Golang/work3]# go run func2.go
Hello mark!

或者也可以赋值传递

    name := "sean"
    sayHello(name)

代码块

[root@LinuxEA /opt/Golang/work3]# cat func2.go
package main
import "fmt"
func sayHello(name string){
    fmt.Printf("Hello %s!",name)
}
func main(){
    sayHello("mark")

    fmt.Println("\n")
    name := "sean"
    sayHello(name)
}

运行

[root@LinuxEA /opt/Golang/work3]# go run func2.go
Hello mark!

Hello sean!

IV. 1.3有返回值有参数函数

写一个计算加法的函数,如下

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

有俩个参数,分别是a和b,都是int类型,返回值也是Int类型。直接return行参即可

在main函数中给add传入两个实参。并且需要一个值来接收。比如a。并且打印

func main(){
    a := add(1,2)
    fmt.Println(a)
}

也可以直接打印fmt.Println(add(1,2))

代码块

package main
import "fmt"
func add(a,b int)int{
    return a + b
}
func main(){
    a := add(1,2)
    fmt.Println(a)
}

运行

[root@LinuxEA /opt/Golang/work3]# go run add.go
3

V. 1.4可变参数

可变参数也需要定义名称,参数类型使用...。三个点

  • 可变参数只能定义一个,并且一般只能定义在末尾

定义a和b,而后定义可变参数args,可以有,也可以没有,使用三个点表示,而后写上类型,这里使用的是int,最后打印并返回一个0 .如下:

并且打印出args类型:

func addN(a,b int,args ...int)  int {
    fmt.Println(a,b,args)
    fmt.Printf("%T",args)
    return 0
}

在main中调用的时候,可以传入args,也可以不传

func main(){
    fmt.Println(addN(1,2))
    fmt.Println(addN(1,2,3,4,5,6))
}

运行

[root@LinuxEA /opt/Golang/work3]# go run addn.go
1 2 []
[]int0
1 2 [3 4 5 6]
[]int0

可以看到,args的类型是一个切片。

VI. 1.5计算可变参数值

如上,现在将可变参数中的值进行相加,可变元素和a,b相加,args是切片。那么,现在通过遍历进行相加。

首先,将a,b相加

    titak := a + b

而后遍历args切片,进行相加

    for _,v := range args {
        titak += v
    }

最后返回

    return titak

代码块

[root@LinuxEA /opt/Golang/work3]# cat addn.go
package main
import "fmt"

func addN(a,b int,args ...int) int  {

    titak := a + b

    for _,v := range args {
        titak += v
    }
    return titak
    
}
func main(){
    fmt.Println(addN(1,2))
    fmt.Println(addN(1,2,3,4,5,6))
}

运行

[root@LinuxEA /opt/Golang/work3]# go run addn.go
3
21

VII. 1.6args函数中传递

接上述的函数。现在创建一个cacl的函数,将addN的args传递进来。

args默认是一个空切片,这时候就可以使用args的解包操作args...。解包的作用是将args从传递中进行解包(在本节案例中,解包后就是int类型),所以这里是有三个点,否则就变成了传递args元素。

...操作只能在切片上

如下:

func cacl(op string,a,b int,args ...int) int {
    switch op {
    case "add":
        return addN(a,b,args...)
    }
    return -1
}

而后在main函数中传递op字符串参数,a,b的int类型,args是可选参数。

cacl("add",1,2):传递给cacl,第一个参数add,第二个1,1对于a,第二个2,2对应2。第三个参数没有,args为空切片。调用addN函数相加

cacl("add",1,2,5):传递给cacl,第一个参数add,第二个1,1对于a,第二个2,2对应2。第三个参数是5,args解包切片中是5。调用addN函数相加

cacl("add",1,2,5,8):传递给cacl,第一个参数add,第二个1,1对于a,第二个2,2对应2。第三个参数是5,args解包切片中是5。第四个参数是8,args解包切片中是8。调用addN函数相加

如下:

func main(){
    fmt.Println(cacl("add",1,2))
    fmt.Println(cacl("add",1,2,5))
    fmt.Println(cacl("add",1,2,5,8))
}

代码块

[root@LinuxEA /opt/Golang/work3]# cat addn2.go
package main
import "fmt"

func addN(a,b int,args ...int) int  {
 
    titak := a + b

    for _,v := range args {
        titak += v
    }
    return titak
    
}
func cacl(op string,a,b int,args ...int) int {
    switch op {
    case "add":
        return addN(a,b,args...)
    }
    return -1
}

func main(){
    fmt.Println(cacl("add",1,2))
    fmt.Println(cacl("add",1,2,5))
    fmt.Println(cacl("add",1,2,5,8))
}

运行

[root@LinuxEA /opt/Golang/work3]# go run addn2.go
3
8
16

除了以上的方式,在main函数中还可以修改,通过args的方式传入

func main(){


  args := []int{1,2,3,4,56,67}
  
  fmt.Println(addN(1,2,args...))
  
  fmt.Println(cacl("add",1,2,args...))
}

运行

[root@LinuxEA /opt/Golang/work3]# go run addn2.go
136
136

VIII. 1.7解包删除切片

如下:

nums := []int{1,2,5,8,0}

删除中间的5

和之前的copy删除类型,用nums[:2],拿出索引start-2,在用nums[3:],拿出索引3到END

nums[:2],nums[3:]...打印

    fmt.Println("nums[:2]:",nums[:2])
    fmt.Println("nums[3:]:",nums[3:])

拿到的结果是

[root@LinuxEA /opt/Golang/work3]# go run del.go
nums[:2]: [1 2]
nums[3:]: [8 0]

加在一起就是1,2,8,0,而后使用append添加到nums中。

  • 这里必须用到nums[3:]...的解包。这是核心
nums = append(nums[:2],nums[3:]...)

代码块

package main
import "fmt"
func main(){
    nums := []int{1,2,5,8,0}
    nums = append(nums[:2],nums[3:]...)
    fmt.Println(nums)
}

运行

[root@LinuxEA /opt/Golang/work3]# go run del.go 
[1 2 8 0]

IX. 1.8返回值

go中,函数所有的分支必须有返回值。在一个函数的逻辑中需要。在上述代码中return了-1,这里返回-1是因为返回值是int类型。如下:

func cacl(op string,a,b int,args ...int) int {
    switch op {
    case "add":
        return addN(a,b,args...)
    }
    return -1
}

return -1,-1在这里是说(只要是int类型就可以 ),不管有没有返回的结果,这里都会返回-1。因为在函数逻辑中这里是有返回值的。

这似乎并不明了,写个简单的示例.

执行两次

    return 1
    return 0

并进行标注,看会发生什么

package main
import "fmt"
func testReturn() int {
    fmt.Println("return 1 前")
    return 1
    fmt.Println("return 1 后")
    return 0
}
func main(){
    fmt.Println(testReturn())
}

运行

[root@LinuxEA /opt/Golang/work3]# go run return.go
return 1 前
1

这里看到只是执行了return 1,这是因为代码执行到return后就不会在执行后面的了。而上述定义的return 2在执行了return 1后是永远都不会执行的。

  • 而在go中支持多个返回值。

###多返回值示例:

cacl函数,有a和b两个行参,满足加减乘除。在go中,支持多个返回值,于是,代码就可以写成这样

return a+b,a-b,a*b,a/b

而return了四个返回值后,也需要4个类型来接收

func calc(a,b int) (int,int,int,int) {
    return a+b,a-b,a*b,a/b
}

代码块

package main
import "fmt"
func calc(a,b int) (int,int,int,int) {
    return a+b,a-b,a*b,a/b
}
func main(){
    fmt.Println(calc(9,3))
}

运行计算,a是9,b是3的加减乘除计算结果

[root@LinuxEA /opt/Golang/work3]# go run calc.go 
12 6 27 3

当然,在main函数中,这里也可以分开传递,并且可以进行单个屏蔽,比如屏蔽a4,也就是除法,使用下划线即可。

func main(){
    a1,a2,a3,_ := calc(9,3)
    fmt.Println(a1,a2,a3)
}

运行

[root@LinuxEA /opt/Golang/work3]# go run calc.go
12 6 27

命名返回值

上述的返回值是没有定义名称的,我们也可以定一个名称,定义名称后就可以直接return 返回值变量的最终结果返回。还是以加减乘除,如下:

func calc2(a,b int) (sum int,diff int,product int,merchant int) {
    sum = a + b
    diff = a - b
    product = a * b 
    merchant = a / b
    return
}
func main(){
    fmt.Println(calc2(10,2))
}

运行

[root@LinuxEA /opt/Golang/work3]# go run calc2.go
12 8 20 5

如果没有任何赋值就会返回0。

命名返回值在代码量较多的时候查看和使用较为不便。

X. 1.9递归

递归是指函数直接或间接调用自己,递归常用于解决分治问题,为相同的小问题进行解决,需要关注终止条件。

计算0到100的和,用n的阶乘:f(n) 1...n

0 - 100的和,等于0-99的和加上100,用函数表示就是f(99)+100

0 - 99的和,等于0-98的和加上99,用函数表示就是f(98)+99

函数就成了f(n) = n + f(n-1),而f(1) = 1的时候

  • 使用递归实现

仍然计算一个1到100的和,假设是Addn的函数,返回值也是int.

return的结果就是n + Addn(n-1)

func Addn(n int) int{
    return n + Addn(n-1)
}

计算0-5的和.

func main(){
    fmt.Println(Addn(5))
}

这样就相当于从5开始计算

Addn(5) => 5 + Addn(4)
Addn(4) => 4 + Addn(3)
Addn(3) => 3 + Addn(2)
Addn(2) => 2 + Addn(1)
Addn(1) = 1 + Addn(0)

终止条件

这样就会一直执行,递归会一直调用自己,形成了死循环。需要一个结束条件语句。

当n等于1的时候就返回

    if n == 1 {
        return 1
    }

如下:

func Addn(n int) int{
    if n == 1 {
        return 1
    }
    return n + Addn(n-1)
}

这样代码执行完成

package main
import "fmt"

func Addn(n int) int{
    if n == 1 {
        return 1
    }
    fmt.Println("计算f(n):",n)
    return n + Addn(n-1)
}
func main(){
    fmt.Println(Addn(5))
}

运行

[root@LinuxEA /opt/Golang/work3]# go run add2.go
计算f(n): 5
计算f(n): 4
计算f(n): 3
计算f(n): 2
15
0 分享

您可以选择一种方式赞助本站

支付宝扫码赞助

支付宝扫码赞助

日期: 2020-11-09分类: Golang

标签: Golang

发表评论