Go 专栏|函数那些事

简介: Go 专栏|函数那些事

QQ图片20220423132354.png

函数定义


函数包括以下几个部分:关键词 func,函数名,参数列表,返回列表和函数体。


func name(param-list) ret-list {
  body
}
复制代码


函数可以没有参数,也可以没有返回值。


func funcA() {
  fmt.Println("i am funcA") // i am funcA
}
复制代码


函数的类型称作函数签名,当两个函数的参数列表和返回列表相同时,则两个函数的类型或签名就相同。


func add(x int, y int) int {
  return x + y
}
func sub(x int, y int) (z int) {
  z = x - y
  return
}
fmt.Printf("%T\n", add) // func(int, int) int
fmt.Printf("%T\n", sub) // func(int, int) int
复制代码


参数


多个相邻类型的参数可以使用简写模式,所以刚才的 addsub 函数还可以这样写:


func add(x, y int) int {
  return x + y
}
func sub(x, y int) (z int) {
  z = x - y
  return
}
复制代码


支持不定参数,使用 ...type 语法。注意不定参数必须是函数的最后一个参数。


func funcSum(args ...int) (ret int) {
  for _, arg := range args {
    ret += arg
  }
  return
}
// 不定参数
fmt.Println(funcSum(1, 2))    // 3
fmt.Println(funcSum(1, 2, 3)) // 6
复制代码


也可以使用 slice 作为实参传入,需要使用 ... 将 slice 展开:


// slice 参数
s := []int{1, 2, 3, 4}
fmt.Println(funcSum(s...)) // 10
复制代码


其实,使用 slice 作为形参同样可以达到相同的效果,但区别就是传参的时候,必须要构造出来一个 slice 才行,没有不定参数使用起来方便。


func funcSum1(args []int) (ret int) {
  for _, arg := range args {
    ret += arg
  }
  return
}
fmt.Println(funcSum1(s))   // 10
复制代码


返回值


函数可以返回一个值,也可以返回多个值。


// 多返回值
func swap(x, y int) (int, int) {
  return y, x
}
// 多返回值
fmt.Println(swap(1, 2)) // 2 1
复制代码


如果有不需要的返回值,使用 _ 将其忽略:


x, _ := swap(1, 2)
fmt.Println(x) // 2
复制代码


支持命名返回值。使用命名返回值的话,直接使用 return 即可,后面不用跟返回值名。


前面不定参数的例子就是通过这种方式来写的:


func funcSum(args ...int) (ret int) {
  for _, arg := range args {
    ret += arg
  }
  return
}
复制代码


再来对比一下,如果不是采用命名返回值,应该怎么写:


func funcSum(args ...int) int {
  ret := 0
  for _, arg := range args {
    ret += arg
  }
  return ret
}
复制代码


匿名函数


匿名函数是指不需要定义函数名的一种函数实现方式。可以直接赋值给函数变量,可以当作实参,也可以作为返回值,还可以直接调用。


// 匿名函数
sum := func(a, b int) int { return a + b }
fmt.Println(sum(1, 2)) // 3
复制代码


作为参数:


// 匿名函数作为参数
func funcSum2(f func(int, int) int, x, y int) int {
  return f(x, y)
}
fmt.Println(funcSum2(sum, 3, 5)) // 8
复制代码


作为返回值:


// 匿名函数作为返回值
func wrap(op string) func(int, int) int {
  switch op {
  case "add":
    return func(a, b int) int {
      return a + b
    }
  case "sub":
    return func(a, b int) int {
      return a + b
    }
  default:
    return nil
  }
}
f := wrap("add")
fmt.Println(f(2, 4)) // 6
复制代码


直接调用:


// 直接调用
fmt.Println(func(a, b int) int { return a + b }(4, 5)) // 9
复制代码


总结


函数在之前的文章中已经使用过了,这篇再系统全面总结一下都有哪些需要注意的点。


包括函数定义,参数,返回和匿名函数。其实还有一个闭包,通过匿名函数来实现。但我感觉闭包使用的并不是很多,就没有写,感兴趣的同学可以自己搜搜看。


函数可以把复杂的程序分成更小的模块,使程序可读性更强,复用性更高,维护性更好。在开发过程中一定要具备将特定功能抽象成函数的能力,而不是将所有代码都写在一起,代码堆成一坨。这样的代码除了不好维护,重点是时间长了自己都不想看。



文章中的脑图和源码都上传到了 GitHub,有需要的同学可自行下载。


地址:github.com/yongxinz/go…



目录
相关文章
|
2月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
208 1
|
3月前
|
存储 Java Go
对比Java学习Go——函数、集合和OOP
Go语言的函数支持声明与调用,具备多返回值、命名返回值等特性,结合`func`关键字与类型后置语法,使函数定义简洁直观。函数可作为一等公民传递、赋值或作为参数,支持匿名函数与闭包。Go通过组合与接口实现面向对象编程,结构体定义数据,方法定义行为,接口实现多态,体现了Go语言的简洁与高效设计。
|
6月前
|
人工智能 Dart Go
Go语言中的make和new函数的区别及使用场景
本文详细解析了Go语言中`make`和`new`函数的使用方法及区别。`make`用于创建切片、映射和通道等引用类型,返回初始化后的值;`new`用于创建任意类型的零值对象,返回指向该对象的指针。文章通过多个示例说明两者的应用场景,并总结了面试中可能遇到的相关问题,如底层实现、使用场景及优缺点等,帮助读者更好地理解和区分这两个函数。
216 1
|
7月前
|
Go 调度
GO语言函数的内部运行机制分析
以上就是Go语言中函数的内部运行机制的概述,展示了函数在Go语言编程中如何发挥作用,以及Go如何使用简洁高效的设计,使得代码更简单,更有逻辑性,更易于理解和维护。尽管这些内容深入了一些底层的概念,但我希望通过这种方式,将这些理论知识更生动、更形象地带给你,让你在理解的同时找到编程的乐趣。
161 5
|
7月前
|
Go Python
函数的定义与调用 -《Go语言实战指南》
本文介绍了 Go 语言中函数的核心特性与用法,包括基本定义格式、调用方式、多返回值、返回值命名、参数类型简写、可变参数、高阶函数及匿名函数等内容。通过示例代码详细展示了如何定义和使用不同类型的函数,使读者能够全面了解 Go 函数的灵活性与强大功能。
147 12
|
JSON 安全 网络协议
go语言使用内置函数和标准库
【10月更文挑战第18天】
187 3
go函数
go函数
110 11
|
编译器 Go C++
Go to Learn Go之函数
Go to Learn Go之函数
144 1
|
Prometheus Cloud Native Go
Go 1.22 标准库 slices 新增函数和一些旧函数增加新特性
Go 1.22 标准库 slices 新增函数和一些旧函数增加新特性
|
安全 编译器 Go
Go 1.21: 泛型函数的全面回顾
Go 1.21: 泛型函数的全面回顾

热门文章

最新文章