golang中的函数问题

本文探讨了Go语言中函数的一些重要特性,包括函数作为参数、函数类型、可变参数等。介绍了如何将函数作为其他函数的参数,强调了函数必须有明确的终止语句。此外,还详细阐述了函数作为类型的优势,特别是在实现通用接口时的灵活性。对于可变参数,文章解释了其内部实现机制——变参本质上是数组切片,并展示了如何在函数调用中使用变参。最后,讨论了如何处理多种类型的变参,通过使用`interface{}`实现类型安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数作为参数,函数是第一类对象,可作为参数传递,只要被调用函数的返回值个数,返回值类型和返回值的顺序与调用函数所需要的实参是一致的,就可以吧这个被调用 的函数当做其他函数的参数。

func f1(a,b,c int)

func f2(a,b int)(int,int,int)

func f1(f2(a,b))函数f1需要三个参数,同时f2返回三个参数

package main

import "fmt"

func pipe(ff func() int) int {
	return ff()
}

type FormatFunc func(s string, x, y int) string

func format(ff FormatFunc, s string, x, y int) string {
	return ff(s, x, y)
}
func main() {
	s1 := pipe(func() int { return 100 })
	s2 := format(func(s string, x, y int) string {
		return fmt.Sprintf(s, x, y)
	}, "%d,%d", 10, 20)
	fmt.Println(s1, s2)
}

有返回值的函数,必须有明确的终止语句。

函数作为类型

函数go语言中也是一种变量,前面多次通过type来定义它,它的类型就是所有拥有相同参数与相同返回值的一种函数类型

type typeName func(input1 inputType1,input2 inputType2[,...])(result resultType1[,...]) 

函数作为类型的最大好处在于可以吧这个类型的函数当做值来传递

package main

import (
	"fmt"
)

func isOdd(v int) bool {  //取奇数
	if v%2 == 0 {
		return false
	}
	return true
}
func isEven(v int) bool { //取偶数
	if v%2 == 0 {
		return true
	}
	return false
}

type boolFunc func(int) bool  

func filter(slice []int, f boolFunc) []int {
	var result []int
	for _, value := range slice {
		if f(value) {
			result = append(result, value)
		}
	}
	return result
}
func main() {
	slice := []int{3, 1, 4, 5, 9, 2}
	fmt.Println("slice=", slice)
	odd := filter(slice, isOdd)
	fmt.Println("odd:", odd)
	even := filter(slice, isEven)
	fmt.Println("even:", even)
}

 在写一些通用的接口的时候,把函数当做值和类型会非常有用,上面的例子中的boolFunc就是一个函数类型,isOdd参数和返回值与boolFunc类型一样,通过这种模式可以实现各种各样的逻辑,使得程序变得非常灵活。

可变参数,函数有着不定数量的参数,在很多时候都会遇到,go语言函数支持可变参数,为了做到这一点,首先需要定义函数使其接收变参

func myfunc(arg  ...int) { }

go语言中,函数的最后一个参数古国是type的形式,那这个函数就是一个变参函数,它可以处理边长的参数,而这个长度可以是0,注意的是在变参函数中,无论变参有多少个,他们的类型全部都一样,以上面的函数为例,函数体中变量arg是一个int类型的切片,所以这函数的参数是一个类似int类型的切片,改参数可以通过前面提到的for循环结构来迭代。

package main

import "fmt"

func main() {
	age := ageMinOrMax("min", 1, 3, 2, 0)
	fmt.Printf("年龄最小的是%d岁\n", age)
	agrArr := []int{7, 9, 3, 5, 1}
	age = ageMinOrMax("max", agrArr...)
	fmt.Printf("年龄最大的是%d岁\n", age)
}
func ageMinOrMax(m string, a ...int) int {
	if len(a) == 0 {
		return 0
	}
	if m == "max" {
		max := a[0]
		for _, v := range a {
			if v > max {
				max = v
			}
		}

		return max

	} else if m == "min" {
		min := a[0]
		for _, v := range a {
			if v < min {
				min = v
			}
		}
		return min
	} else {
		e := -1
		return e
	}
}

 

package main

import "fmt"

func main() {
	ageArr := []int{7, 9, 3, 5, 1}
	f1(ageArr...)
}
func f1(arr ...int) {
	f2(arr...)
	fmt.Println("")
	f3(arr)
}
func f2(arr ...int) {
	for _, char := range arr {
		fmt.Printf("%d", char)
	}
}
func f3(arr []int) {
	for _, char := range arr {
		fmt.Printf("%d", char)
	}
}
package main

import "fmt"

func main() {
	ageArr := []int{7, 9, 3, 5, 1}
	f1(ageArr...)
}
func f1(arr ...int) {
	f2(arr...)
	fmt.Println("")
	f3(arr...)
}
func f2(arr ...int) {
	for _, char := range arr {
		fmt.Printf("%d", char)
	}
}

func f3(arr ...int) {
	for _, char := range arr {
		fmt.Printf("%d", char)
	}
}

// func f3(arr []int) {
// 	for _, char := range arr {
// 		fmt.Printf("%d", char)
// 	}
// }

变长参数可以作为对应来兴的slice进行二次传递,从内部实现机制上来说,类型...int本质上是一个数组切片,[]int,也就是arr可以用for循环来获取每个元素的值的原因。

前后写需要保持一直,f3(arr) 对应的func f3(arr []int)后者 f3(arr ...)

函数f2和f3的最大区别在于调用方式

f2(1,3,7,13)  可变参数,随便写

f3([]int{1,3,7,13})需要加上[]int{}来构造一个数组切片示例

最后关于可变参数为多种类型的情况,之前的例子都是吧变参类型约束为一种类型,但如果希望传递任意类型,可以指定类型为interface{},也就是接口。

func  Printf(format string,args...interface{}) {

}

常用的printf函数就是一个变参函数,而且不限制参数类型,用interface{}传递任意类型数据是go语言的习惯用法,interface{}是类型安全的,除了使用空接口解决这个问题,还可以使用结构体解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值