go 函数
函数声明和注释
1、函数声明: func 函数名字 (参数列表) [(返回值列表)] {}

func add(a, b int) (int, int) {
}
2. 注释,两种注释,单行注释: // 和多行注释 /* */

3、 一个.go文件初始化,先执行全局变量,再执行init()函数,init()函数自动调用
4、多个包引用,如果引用顺序是main -> add -> test,初始化顺序:test.go的全局变量->test.go的init()->add全局变量->add.go的init()->main.go全局变量->main.go的init()

函数特点
- 不支持重载,一个包不能有两个名字一样的函数
- 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量
- 匿名函数
- 多返回值
样例:
package main
import "fmt"
type op_func func(int, int) int
func add(a, b int) int {
return a + b
}
func sub(a, b int) int {
return a - b
}
func operator(op op_func, a int, b int) int {
return op(a, b)
}
func main() {
c := add
fmt.Println(c)
sum := operator(c, 100, 200)
fmt.Println(sum)
var d op_func
d = sub
fmt.Println(d)
sub := operator(d, 100, 200)
fmt.Println(sub)
}
自定义函数
demo
package main
import "fmt"
type add_func func(int, int) int
func add(a, b int) int {
return a + b
}
func operator(op add_func, a int, b int) int {
//使⽤用传进来的函数,进⾏行行操作
return op(a, b)
}
func main() {
c := add
fmt.Println(c)
sum := operator(c, 100, 200)
fmt.Println(sum)
}

函数参数传递方式
- 值传递
- 引用传递
注意:无论是值传递,还是引用传递,传递给函数的都是变量的副本。不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
map、slice、chan、指针、interface默认以引用的方式传递。
命名返回值的名字
func add(a, b int) (c int) {
c = a + b
return
}
func calc(a, b int) (sum int, avg int) {
sum = a + b
avg = (a + b)/2
return
}
_标识符,用来忽略返回值
func calc(a, b int) (sum int, avg int) {
sum = a + b
avg = (a + b) / 2
return
}
func main() {
sum, _ := calc(100, 200)
}
可变参数
- 0个或多个参数
func add(arg…int) int {
}
- 1个或多个参数
func add(a int, arg…int) int {
}
- 2个或多个参数
func add(a int, b int, arg…int) int {
}
注意:其中arg是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数。
样例:
package main
import "fmt"
func add(a int, arg...int) int{
var sum int = a
for i := 0; i < len(arg); i ++ {
sum += arg[i]
}
return sum
}
func add_string(a string, arg...string) (result string) {
result = a
for i := 0; i < len(arg); i ++ {
result += arg[i]
}
return
}
func main() {
sum := add(10, 1 , 2, 3)
fmt.Println(sum)
str := add_string("hello ", "world ", "wang")
fmt.Println(str)
}
匿名函数
样例:
package main
import "fmt"
var(
result = func(a1, b1 int) int{
return a1 + b1
}
)
func test(a, b int) int {
result := func(a1, b1 int) int{
return a1 + b1
}(a, b)
return result
}
func test1(a, b int) int {
result := func(a1, b1 int) int{
return a1 + b1
}
return result(a, b)
}
func main() {
sum := test(10 , 20)
fmt.Println(sum)
sum1 := test1(1, 2)
fmt.Println(sum1)
fmt.Println(result(3,4))
}
defer用途
- 当函数返回时,执行defer语句。因此,可以用来做资源清理
- 多个defer语句,按先进后出的方式执行
- defer语句中的变量,在defer声明时就决定了
样例:
package main
import "fmt"
func main() {
var i int = 0
defer fmt.Println(i)
defer fmt.Println("second")
i = 10
fmt.Println(i)
}

说明:上面代码执行,先将defer压入栈中,当main函数执行完成后,再执行defer内容。多个defer语句,按先进后出的方式执行。同时defer语句的变量i声明时为0,所以结果也为0
使用场景举例:
1、关闭文件句柄
func read() {
//文件操作
file := open(filename)
defer file.Close()
}
2、锁资源释放
func read() {
mc.Lock()
defer mc.Unlock()
// 其他操作
}
3、数据库连接释放
func read() {
conn := openDatabase()
defer conn.Close()
//其他操作
}
内置函数
- close:主要用来关闭channel
- len:用来求长度,比如string、array、slice、map、channel
- new:用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
- make:用来分配内存,主要用来分配引用类型,比如chan、map、slice
- append:用来追加元素到数组、slice中
- panic和recover:用来做错误处理
new和make的区别

package main
import "fmt"
func test() {
s1 := new([]int)
fmt.Println(s1)
s2 := make([]int, 10)
fmt.Println(s2)
*s1 = make([]int, 5)
(*s1)[0] = 100
s2[0] = 100
fmt.Println(s1)
return
}
func main() {
test()
}

递归函数
函数调用自己,就叫做递归。
递归的设计原则
- 一个大的问题能够分解成相似的小问题
- 定义好出口条件
样例:
package main
import (
"fmt"
"time"
)
func recusive(n int) {
fmt.Println("hello", n)
time.Sleep(time.Second)
if n > 10 {
return
}
recusive(n + 1)
}
func factor(n int) int {
if n == 1 {
return 1
}
return factor(n-1) * n
}
func fab(n int) int {
if n <= 1 {
return 1
}
return fab(n-1) + fab(n-2)
}
func main() {
//fmt.Println(factor(5))
recusive(0)
/*for i := 0; i < 10; i++ {
fmt.Println(fab(i))
}*/
}
闭包
一个函数和与其相关的引⽤用环境组合⽽而成的实体。
demo1:
func Adder() func(int) int {
var x int
f := func(i int) int {
x = x + i
return x
}
return f
}
func testClosure() {
f1 := Adder()
fmt.Println(f1(10))
fmt.Println(f1(20))
fmt.Println(f1(30))
f2 := Adder()
fmt.Println(f2(10))
fmt.Println(f2(20))
fmt.Println(f2(30))
}

demo2:
package main
import (
"fmt"
"strings"
)
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
bmp := makeSuffixFunc(".bmp")
jpg := makeSuffixFunc(".jpg")
fmt.Println(bmp("test"))
fmt.Println(jpg("test"))
}

浙公网安备 33010602011771号