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"))
}

 

posted @ 2017-08-24 15:20  shhnwangjian  阅读(229)  评论(0编辑  收藏  举报