go语言的学习之函数与指针

函数的定义格式

func funcname (/*参数列表*/)(/*a type, b type*/){
	//函数体
	return a, b
}

不定参数列表的函数

package main

import "fmt"

// ...int 不定长参数,可以为0个或多个
func sum(numbers ...int) int {
	s := 0
	for _, v := range numbers {
		s += v
	}
	return s
}

func main() {
	fmt.Println(sum(1, 2, 3))
}

递归函数

package main

import "fmt"

// 累加100
func sum(n int) int {
	if n == 0 {
		return 0
	}
	return n + sum(n-1)
}

func main() {
	fmt.Println(sum(100))
}

函数类型

函数也是一种数据类型,可以通过type给同一类型的函数起别名

package main

import "fmt"

func add(a, b int) int {
	return a + b
}

func minus(a, b int) int {
	return a - b
}

func calc(a, b int, mf myfunc) int {
	res := mf(a, b)
	return res
}

/*
给func(int, int) int 这个类型的函数起名为 myfunc
类似于给golang已有的基本数据类型起别名一样,如下:
type long int64  // 这里就是给int64类型起了一个long的别名
var num long //此时num的类型其实就是int64
这里就是将有两个int类型的入参,返回值为一个int的函数,命名为myfun
*/
type myfunc func(int, int) int

func main() {
	var res int
	res = add(1, 1)
	fmt.Println(res)
	// 因为calc的其中一个参数是myfunc类型的函数,而add符合这个要求(两个int入参,返回值为一个int)所以可以将add当作参数传入calc函数中使用,这么做的目的是在于,可以通过calc函数实现加减法,方便以后的拓展,比如说想实现乘法,只需要写一个符合myfunc类型的乘法函数,就可以通过calc掉用它
	// 总的来说,是方便给代码增加功能
	res = calc(1, 1, add) // 等价于add(1,1)
	fmt.Println(res)
}

匿名函数与闭包

1> 匿名函数的定义方式

package main

import "fmt"

func main() {
	//无参数无返回值匿名函数,赋值给f1,并通过f1()调用
	f1 := func() {
		fmt.Println("无参数无返回值的匿名函数")
	}
	f1()
	//有参数有返回值的匿名函数,将返回值赋给sum,直接在定义匿名函数的同时就掉用
	sum := func(a, b int) int {
		return a + b
	}(1, 2)
	fmt.Println(sum)
}

2> 闭包
所谓闭包就是一个函数“捕获”了和它在同一作用域的其它常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些常量或者变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在

package main

import "fmt"

func squares() func() int {
	x := 0
	f := func() int {
		x++
		return x * x
	}
	return f
}

func main() {
	f := squares()
	fmt.Println(f()) // 1
	fmt.Println(f()) // 4
	fmt.Println(f()) // 9
	fmt.Println(f()) // 16
}

函数squares返回另一个类型为 func() int 的函数。对squares的一次调用会生成一个局部变量x并返回一个匿名函数。每次调用时匿名函数时,该函数都会先使x的值加1,再返回x的平方。第二次调用squares时,会生成第二个x变量,并返回一个新的匿名函数。新匿名函数操作的是第二个x变量。
通过这个例子,我们看到变量的生命周期不由它的作用域决定:squares返回后,变量x仍然隐式的存在于f中。

指针

首先需要清楚一个概念:值传递和引用传递的区别

  • 值传递会就将变量的值拷贝一份,并不会改变原来的值
  • 引用传递是将变量的地址传了出去,会改变原来的值
  • 而指针,则是代表着这个变量的内存地址,也就是这个变量的引用,也就是说,所有通过指针来传递的数据,都会改变原来的值

go语言的指针不能运算
go语言只有值传递一种方式(但是我们可以用指针来实现引用传递的效果)

package main

import "fmt"

func swap(a, b int) {
	a, b = b, a
}

func main() {
	a, b := 3, 4
	swap(a, b)
	// 这里没有将a,b的值交换过来,因为go里面都是值传递,
	//在swap函数里,对a和b的值进行了一份拷贝,也就是说,在swap函数里面,a与b的值交换过来了,
	//但是在外部,a和b的值没有发生变化,如果想通过swap函数使a和b的值交换,可以使用指针来实现
	fmt.Println(a, b) // 3, 4
}

使用指针来交换a,b的值

package main

import "fmt"

func swap(a, b *int) {
	*a, *b = *b, *a
}

func main() {
	a, b := 3, 4
	swap(&a, &b)
	fmt.Println(a, b) // 4, 3
}

你可能感兴趣的:(golang)