Golang的函数定义和使用

1,953 阅读4分钟

Go语言里的函数可分为两种:

  1. 带名字的叫普通函数
  2. 没带名字的叫匿名函数

函数的申明

使用func关键字,后面一次接函数名参数列表返回值列表用{}包裹的代码块

func 函数名(形式参数列表)(返回值列表){
    函数体
}

函数的可变参数

多个类型一致的参数

// 使用 ...类型,表示一个元素为int类型的切片
func TestParams(args ...string) {
  fmt.Printf("args: %v\n", args)
}


func main() {
  type_func.TestParams("A", "B", "C")
  type_func.TestParams("A", "B", "C", "D")
  // args: [A B C]
  // args: [A B C D]
}

... 是 Go 语言为了方便程序员写代码而实现的语法糖,如果该函数下有多个类型的参数,这个语法糖必须得是最后一个参数。

这个语法糖,只能在定义函数时使用。

多个类型不一致的参数

上面的例子中,我们的参数类型都为string,如果你希望多个参数切这些参数的类型都不一样,可以指定类型...interface{},然后再遍历。

下面代码使用之前说过的switcharg.(type)来演示不一致参数的情况。

func main() {
  var v1 int = 1
  var v2 int64 = 234
  var v3 string = "hello"
  var v4 float32 = 1.234
  PrintType(v1, v2, v3, v4)
}

func PrintType(args ...interface{}) {
  for _, arg := range args {
    switch arg.(type) {
    case int:
      fmt.Println(arg, "is an int value.")
    case string:
      fmt.Println(arg, "is a string value.")
    case int64:
      fmt.Println(arg, "is an int64 value.")
    default:
      fmt.Println(arg, "is an unknown type.")
    }
  }
}

函数传递可变参数

上面提到了可以使用 ... 来接收多个参数,除此之外,它还有一个用法,就是用来解序列,将函数的可变参数(一个切片)一个一个取出来,传递给另一个可变参数的函数,而不是传递可变参数变量本身。

这个方法,只能再给函数传递参数的时候使用,这两个是成对出现的。

func main() {

  args := []int{1, 2, 3, 4}
  test(args...)
}

func test(args ...int) {
  fmt.Printf("args: %v\n", args)
}

函数的返回值

函数的返回值是在定义函数的时候就已经确定好了。

一般有两种情况,一种是没有返回值,一种是有。同事Go语言支持返回多个值。

当函数没有指定返回值时。函数体可以使用return来结束函数的运行,但return后不能跟任何东西。

Go返回多个值的函数:

func main() {

  args := []int{1, 2, 3, 4}
  test(args...)

  number1, number2, string1 := returnTwo()

  fmt.Printf("number1: %v\n", number1)
  fmt.Printf("number2: %v\n", number2)
  fmt.Printf("string1: %v\n", string1)
}

func returnTwo() (int, int, string) {
  return 1, 2, "111"
}

// 结果
number1: 1
number2: 2
string1: 111

匿名函数

匿名函数,就是没有名字的函数,它只有函数逻辑体。

下面就是一个立即执行的函数。

立即执行函数

func(data int) {
    fmt.Println("hello", data)
}(100)

作为回调函数使用

func main() {
  excute(func(str string) {
    print("call back" + str)
  })
}

func excute(call func(string)) {
  call("123")
}

// 结果
call back123

这些东西其实在其他语言里也有同样的概念,想JS里面的匿名函数

函数作为变量

在Go里面函数,也有和JS一样的用法和概念,比如将函数赋值给变量,临时性死区等。

下面是将函数赋值给变量的方式。

func main() {
  // func1()  // 不删除会形成临时死区
  var func1 = func() {
    print("success!!!!")
  }
  func1()
}
  // 结果
  success!!!!

然后换种方式

func main() {
  func1()  // 不删除会形成临时死区
  var func1 = func() {
    print("success!!!!")
  }
}

执行时会报错.\main.go:20:2: undefined: func1。原因是将匿名函数赋值给变量之后,在定义func1前的代码是找不到这个变量的.

函数和方法

在看其他代码的时候有时候会出现像这样定义函数:

func main() {
  person1 := Person{"my name"}
  person1.printName()
}

// 定义一个名为Person的结构体
type Person struct {
  name string
}

// 定义一个与Person绑定的方法
func (p Person) printName() {
  fmt.Print(p.name)
}

// go run main.go后的结果
my name

像这种定义函数的其实是Go里面的方法,给结构体定义方法。通过函数名称前的 (p Person),与结构体进行绑定。

方法,是一种特殊的函数。当你一个函数和对象/结构体进行绑定的时候,我们就称这个函数是一个方法。