go语法——函数

学习go语言之前,我们应该知道go语言是一个函数式编程语言,函数是重中之重,所以本部分介绍了Go语言基本的函数用法以及,为什么说go语言是一个函数式编程语言

一个简单函数

在go语言中,函数的命名方式与变量相同,都是关键字,函数名、类型这种,类型写在最后的方式

函数具体写法如下:

func eval(a, b, int,op string) int{
	...
}

下面是一个简单的函数写法及调用方法:

package main
import (
	"fmt"
)
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("unsupported operation: "+op)
	}
}

func main(){
	fmt.Println(eval(3, 4, "*"))
}

多返回值的函数

先看一个两个返回值的函数

在go语言中,前面也提到过,go语言支持多个返回值,现在介绍的是go语言的,两个返回值的写法:

// 两个返回值的函数
func div(a,b int) (int,int){ // 带余数除法
	return a/b, a%b
}

如上,在两个返回值的函数写法中,在定义返回值类型的地方再写一个返回值的类型即可

返回值分不清?来起个名吧

go语言支持为函数的返回值起名字,具体的写法如下:

package main

import (
	"fmt"
)

// 给返回值起名
func div(a,b int) (q,r int){// 带余数除法
	
	//方法一:
	q = a/b
	r=a%b
	return

	// 方法二:
	return a/b, a%b
}

func main(){
	q, r := div(13,3) //:=定义它们
	fmt.Println(q, r)
}

上述代码可以看出对返回值起名时遵循变量定义时,变量在前,类型在后的方式,在函数体中存在这么两种写法

方法一指定两个返回值q,r分别代表什么,然后返回;

方法二不指定具体代表,按照默认先后顺序进行返回,在主函数体内选取变量进行接受;函数返回值q,r与主函数内接收的q,r没有关联,变量名随意取,不要求相同

注意上述代码返回值代码内起名这种方式仅仅用于简单函数,复杂函数会增加代码复杂度,对调用者而言没有区别

函数返回错误

在其他语言中函数执行报错时会中断整个程序,而go语言可以自定义返回错误信息,并借助多返回值的优势,帮助使用者调试代码

修改一下上次说到的四则运算代码,示例:

package main

import (
	"fmt"
	"math"
	"reflect"
	"runtime"
)
func div(a,b int) (q,r int){
	return a/b, a%b
}
func eval2(a, b int, op string) (int, error) {
	switch op {
	case "+":
		return a+b,nil
	case "-":
		return a-b,nil
	case "*":
		return a*b,nil
	case "/":
		//多返回值使用‘_’表示接受不使用
		q, _ := div(a,b)
		return q,nil
	default:
		// panic("unsupported operation: "+op)
		return 0,fmt.Errorf("unsupported operation: %s", op)
		// 自定义错误信息输出
	}
}

func main(){
	if result, err := eval2(3, 4, "/");err==nil{
		fmt.Println(result)
	}else{
		fmt.Println("Error: ", err)
	}
}

上述代码中,函数拥有两个返回值int类型和erroe类型,由于go语言中定义的变量必须使用,所以在每个返回值后面,再多返回一个nil表示error类型返回值,且无错误;

在主函数的if中调用eval2函数,按照switch逻辑,将调用div函数进行运算,并返回两个返回值,查看代码我们可以发现div也是两个返回值,如果我们只想要其中的一个返回值的时候应该怎么办呢?

类似与下面一句代码,当我们不想要某个返回值时只需要使用_便可以表示接收不使用

q, _ := div(a,b)

回到刚刚的话题,刚刚定于的error类型如何使用呢?从代码来看,如果我们输入参数eval2(3, 4, "z"),很明显,我们定义的eval2函数没法处理z这个参数,这时候就会触发default中定义的error处理

default中的return首先将int类型返回值返回一个0,然后使用fmt.Errorf错误信息输出语句输出错误参数并返回到主程序中并使用err接收,if判断err不为nil,则输出正常运行结果,否则运行自定义错误信息

go——函数式编程语言

go语言相交之C++等其他语言,没有默认参数、可选参数、函数重载等花哨的用法

仅有可变参数列表这一种用法,关于这两点我们通过两段代码验证一下

参数可以为函数

package main

import (
	"fmt"
	"math"
	"reflect"
	"runtime"
)

// go语言是一个函数式编程语言,体现如下,函数内的函数
func apply(op func(int, int) int, a,b int) int {
	p := reflect.ValueOf(op).Pointer()
	opName := runtime.FuncForPC(p).Name()
	// 获得函数名
	
	fmt.Printf("函数名是: %s" + "(%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(apply(Pow, 3 , 4))
	// 函数直接写在调用处,匿名函数,无需写函数名
	fmt.Println(apply(
		func(a,b int) int{
			return int(math.Pow(float64(a), float64(b)))
		},3 , 4))

	fmt.Println(sum(1,2,3,4,5))
}

如上代码,观察函数apply,包含三个参数和一个返回值,其中,第一个参数是一个函数,这个函数拥有两个参数和一个返回值

这三个参数在函数D调用时,以D(A,B,C)的形式调用

apply(Pow, 3 , 4)

这句话便是一个举例用法,Pow为传入的函数名,3,4是其他参数,首先apply获取到传入并运行的实际的函数名称(此处是Pow),然后输出函数名和传入的另外两个参数,在return处调用参数函数op,即Pow

Pow的参数便是a,b

实际上main中调用部分传入的Pow甚至不需要提前定义

可以写成如下这样

// 函数直接写在调用处,匿名函数,无需写函数名
	fmt.Println(apply(
		func(a,b int) int{
			return int(math.Pow(float64(a), float64(b)))
		},3 , 4))

采用匿名函数的方式,直接将函数写在调用处,此方法不需要写传入的函数名

可变参数列表

关于这部分比较简单,只需要记住...即可,在go语言中...代表无限制参数数量

package main

import (
	"fmt"
	"math"
	"reflect"
	"runtime"
)

func sum(numbers ...int) int{
	//...代表任意数量参数
	s:=0
	for i:=range numbers{
		s+=numbers[i]
	}
	return s
}

func main(){
	
	fmt.Println(sum(1,2,3,4,5))
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务