Go | 函数的使用细节和注意事项

简介: Go | 函数的使用细节和注意事项

细节汇总


  1. 函数的形参列表可以是多个,返回值列表也可以是多个
  2. 形参列表和返回值列表的数据类型,可以是值类型、也可以是引用类型
  3. 函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写表示该函数可以被本包文件和其它文件使用,类似public;首字母小写只能被本包文件使用,类似private。
  4. 函数中的变量是局部的,外部不能访问。作用域
  5. 基本数据类型和数组都是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值,
  6. 如果希望函数内的变量能够修改函数外的变量,可以传入变量的地址(&),函数内以指针的方式操作变量,从效果上看类似引用
  7. Go函数不支持函数重载。
  8. 在Go中,函数也是一种数据类型,可以赋值给一个变量,则该变量是一个函数类型的变量,通过该变量可以对函数调用。
  9. 函数既然是一种数据类型,因此在Go中,函数也可以作为形参,并且调用。(回调函数)
  10. 为了简化数据类型定义,Go支持自定义数据类型
  • 语法: type 自定数据类型名 数据类型  (相当于一个别名)
  • 案例: type myInt int 这时,myInt就等价于int来使用了
  • type mySum  func(int, int) int  这时,mySum就等价于func(int, int) int
  1. 支持对函数返回值命名(可以不受返回值顺序限制)
  2. 使用 _ 下划线标识符,忽略返回值。(占位符)
  3. Go支持可变参数


值传递和指针传递


func test(n1 int) {
  n1 = n1 + 10
  fmt.Println("test n1=", n1)
}
// 指针类型接收处理
func test02(n2 *int) {
  *n2 = *n2 + 10
  fmt.Println("test02 n2=", *n2)
}
func main() {
  n1 := 20
  n2 := 2
  test(n1) // 值类型
  test02(&n2) // 指针类型
  fmt.Println("main n1=", n1)
  fmt.Println("main n2=", n2)
}


什么是重载


重载: 函数名相同,但是形参不同或者数据类型不同的情况。

Golang语言中是不支持传统的函数重载的,fn redeclared in this block

Golang语言是支持可变参数的,空接口的形式

image.png


函数类型的变量


类型: func(int, int) int

func getSum(n1 int, n2 int) int {
  return n1 + n2
}
func getSums(n1 int, n2 int, n3 int) int {
  return n1 + n2 + n3
}
// main 函数
sumFn := getSum
res := sumFn(10, 20)
fmt.Printf("%T %v\n", res, res) // int 30
fmt.Printf("%T \n", sumFn) // func(int, int) int
sumsFn := getSums
result := sumsFn(10, 20, 30)
fmt.Printf("result : %T %v\n", result, result) // result : int 60
fmt.Printf("sumsFn类型:%T \n", sumFn) // sumsFn类型:func(int, int) int


函数作为形参传入


func getSum(n1 int, n2 int) int {
  return n1 + n2
}
func testFn(fnVar func(int, int) int, num1 int, num2 int) int {
  return fnVar(num1, num2) // 调用传入的函数,并返回值
}
// 函数类型形参
sumFn := getSum
total := testFn(sumFn, 1, 2)
fmt.Println("total=", total) // 3


自定义数据类型


  1. 自定义函数数据类型, 相当于起了一个别名
type mySum func(int, int) int
func testFn(fnVar mySum, num1 int, num2 int) int {
  return fnVar(num1, num2)
}
// func testFn(fnVar func(int, int) int, num1 int, num2 int) int {
//  return fnVar(num1, num2)
// }
  1. 自定义数据类型
// main函数下
type myInt int
var num1 myInt = 2
// var num2 int = num1 // 这样是报错的, myInt和int并不等价
var num2 int = int(num1) // 显式类型转换
fmt.Printf("num1的类型:%T 值:%v \n", num1, num1) // num1的类型:main.myInt 值:2
fmt.Printf("num2的类型:%T 值:%v \n", num2, num2) // num2的类型:int 值:2
  1. 定义的类型: 包名.类型名,如:utils.myInt
// 以下是utils包
package utils
import "fmt"
func TestFn() string {
  fmt.Println("TestFn 函数被调用")
  type myInt int
  var n myInt = 10
  fmt.Printf("n的类型:%T 值:%v", n, n) // n的类型:utils.myInt 值:10
  return "hahaha"
}


返回值命名


func sumSub(n1 int, n2 int) (sum int, sub int) {
    // 这里不需要声明sum, sub变量了,也不用在return时写
  sum = n1 + n2
  sub = n1 - n2
  return
}
// main函数
sum, sub := sumSub(9, 8)
fmt.Println("sum=", sum, "sub=", sub) // sum= 17 sub= 1


可变参数


基本语法

  1. 支持零到多个参数

func sum(args... int) {}

  1. 支持1到多个参数

func sum(n1 int, args... int) {}

args:就是一个承接的变量名,可以自定义,如:func sum(n1 int, **vars**... int) {}


说明:


  • args是slice切片,通过args[index]可以访问到各个值
  • args必须放到形参列表的最后面


参数个数可变

func sumV2(n1 int, args ...int) int {
  sum := n1
  fmt.Printf("args类型是:%T\n", args) // args类型是:[]int
  // 遍历args切片
  for i := 0; i < len(args); i++ {
    sum += args[i]
  }
  return sum
}
// main函数
// 参数可变
total02 := sumV2(1, 2, 3, 4)
fmt.Println("total02=", total02) // total02= 10


总结练习


交换变量a, b的值

package main
import "fmt"
func swap(n1 *int, n2 *int) {
  *n1 = *n1 + *n2
  *n2 = *n1 - *n2 // *n1
  *n1 = *n1 - *n2 // *n2
}
func main() {
  a := 12
  b := 20
  swap(&a, &b)
  fmt.Println("a = ", a, "b = ", b)
}


目录
相关文章
|
13天前
|
JSON JavaScript Go
Go 语言学习指南:变量、循环、函数、数据类型、Web 框架等全面解析
掌握 Go 语言的常见概念,如变量、循环、条件语句、函数、数据类型等等。深入了解 Go 基础知识的好起点是查阅 Go 官方文档
582 2
|
5天前
|
存储 算法 Go
go语言中的延迟执行函数
【5月更文挑战第13天】`defer`是Go语言中用于延迟执行函数的关键字,尤其适用于资源管理,如文件关闭和锁的释放。它在函数返回前按照LIFO顺序执行,确保资源在任何返回路径下都能正确释放。`defer`可以拦截`panic`并在函数返回前执行,但无法阻止某些致命的`panic`。此外,`defer`可用于修改返回值、输出调试信息和还原变量值。尽管在某些场景下可能影响性能,但Go的优化使得其在多数情况下性能表现良好,特别是在资源清理方面。在Go 1.20及以后的版本,`defer`的性能已显著提升,尤其是在高计算量的场景下。
231 2
|
13天前
|
Go 数据处理
Go杂记1-切片Slice作为函数参数那点事儿
Go杂记1-切片Slice作为函数参数那点事儿
16 0
|
13天前
|
存储 Go 开发者
【Go语言专栏】函数在Go语言中的使用与实现
【4月更文挑战第30天】本文介绍了Go语言中函数的使用和实现,包括函数定义、参数传递、返回值、匿名函数、变长参数、函数类型、闭包和错误处理。通过示例展示了如何定义和调用函数,以及如何利用闭包和递归解决问题。此外,还提到了Go函数作为一等公民的特性,允许存储和传递。进一步学习可参考官方文档和相关书籍。
|
13天前
|
Go
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
【4月更文挑战第21天】Go语言函数是代码组织的基本单元,用于封装可重用逻辑。本文介绍了函数定义(包括基本形式、命名、参数列表和多返回值)、调用以及匿名函数与闭包。在函数定义时,注意参数命名和注释,避免参数顺序混淆。在调用时,要检查并处理多返回值中的错误。理解闭包原理,小心处理外部变量引用,以提升代码质量和可维护性。通过实践和示例,能更好地掌握Go语言函数。
31 1
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
|
13天前
|
程序员 Go API
【Go语言快速上手(二)】 分支与循环&函数讲解
【Go语言快速上手(二)】 分支与循环&函数讲解
|
13天前
|
存储 Go 开发者
Golang深入浅出之-Go语言字符串操作:常见函数与面试示例
【4月更文挑战第20天】Go语言字符串是不可变的字节序列,采用UTF-8编码。本文介绍了字符串基础,如拼接(`+`或`fmt.Sprintf()`)、长度与索引、切片、查找与替换(`strings`包)以及转换与修剪。常见问题包括字符串不可变性、UTF-8编码处理、切片与容量以及查找与替换的边界条件。通过理解和实践这些函数及注意事项,能提升Go语言编程能力。
29 0
|
13天前
|
自然语言处理 数据挖掘 程序员
《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)(下)
《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)(上)
28 1
|
13天前
|
数据采集 搜索推荐 Go
《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)(上)
《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)
29 1
|
13天前
|
存储 缓存 安全
掌握Go语言:Go语言Map,高效键值对集合的应用与注意事项详解(26)
掌握Go语言:Go语言Map,高效键值对集合的应用与注意事项详解(26)