首页 > Go学习 > Go语言的函数和常见内置函数
2021
09-02

Go语言的函数和常见内置函数

函数是基本的代码块,用于执行一个任务。

Go语言最少有个main()函数,一个程序启动后首先会自动执行init()函数(该函数可以省略),然后自动执行main()函数

函数声明告诉了编译器函数的名称,返回类型,和参数

func function_name( [parameter list] ) [return_types] {
   //函数体
}
有些功能不需要返回值,这种情况下return_types不是必须的

func func_name(x int, y string) (string, int) {}
表示传入的参数第一个是整形,第二个是字符串类型
返回两个值,第一个是字符串类型,第二个是整形

func func_name(x , y int) (string, int) {}
表示传入的参数两个都是整形型

不定参数

有时候我们传入的参数是不固定的,这是需要使用在指定参数类型时使用三个点(...)作为前缀

func demo(key int , args ...int){
    fmt.Println(key)
    for _ , v := range args {
        fmt.Println(v)
    }
}

...是Go语言为了方便实现的语法糖,这个语法糖必须是最后一个参数,表示一个指定类型的切片
以上代码表示demo函数接受至少一个参数,其中第一个参数保存在变量key中,其余所有参数保存在一个args的切片中

以上代码我们需要传入的所有参数都是指定的类型,那么如果有时候连传入参数的类型也不确定怎么办呢?
我们知道,一个空接口的实例可以承载任意类型的值,那么我们可以这样写

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

...还有一个用法就是用来在给函数传值时将一个切片展开

var a = [] int {1,2,3,4,5}
demo(a...)
//...会自动展开变量a
//相当于demo(1,2,3,4,5)

函数的返回值

可以返回多个值
func swap(x, y string) (string, string) {
    return y, x
}

当函数没有返回值时可以使用一个空的return语句来结束函数的运行

返回指定的变量
func (x int) (y int){
    y = x*2
    //这里不能使用 := ,因为在返回值那里已经声明了变量y
    return
    //直接使用一个空的return语句返回指定的变量y
}

函数值传递

值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,不会影响到实际参数

默认情况下,Go语言使用的是值传递,即在调用过程中不会影响到实际参数

函数引用传递

引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数

引用传递指针参数传递到函数内

func swap(x *int, y *int) {
    var temp int
    temp = *x
    *x = *y
    *y = temp
}
//上面函数的功能为交换两个参数的值
var a int = 100
var b int = 200
swap(&a, &b)
fmt.Printf("交换后,a 的值 : %d\n", a )
fmt.Printf("交换后,b 的值 : %d\n", b )
执行后显示:
交换后,a 的值 : 200
交换后,b 的值 : 100

Go中的匿名函数

Go语言中一个函数内部是不允许再次定义一个正常函数的,但是可以使用匿名函数

匿名函数是一个"内联"语句或表达式,可作为闭包

匿名函数的优越性在于可以直接使用函数内的变量,不必申明

func demo(){
    i := 1
    func (){
        i+=1
    }()
    fmt.Print(i) //2
}
在匿名函数定义在最后添加括号()表示运行该匿名函数

工厂函数

一个返回值为一个函数的函数可以被称之为工厂函数

func get_num() func() int {
    i := 1
    return func() int {
        i+=1
        return i
    }
}

func main(){
    next_num := get_num()
    fmt.Println(next_num())  //1
    fmt.Println(next_num())  //2

    nexe_num2 := get_num()
    fmt.Println(next_num2())  //1
    fmt.Println(next_num2())  //2
}

函数方法

一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针

func (variable_name variable_data_type) function_name() [return_type]{
    /* 函数体*/
}


type Circle struct {
    radius float64
}

func main() {
    var c1 Circle
    c1.radius = 10.00
    fmt.Println("圆的面积 = ", c1.getArea())
}

//该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
    //c.radius 即为 Circle 类型对象中的属性,如果不使用可以使用空白标识符(_)
    return 3.14 * c.radius * c.radius
}

函数中的延迟语句defer

在defer后面跟一个语句,就能实现将这个语句延迟到当前函数执行完后再执行

有return语句的话defer是return后才调用的

func main(){
    name := "Go"
    defer fmt.Println(name)

    name = "Python"
    fmt.Println(name)
}

会输出:
Python
Go

从上面示例中可以看出来,defer关键词后面的语句是在整个函数执行完成后才执行

上例中name值在后面进行了重新赋值,后续调用defer的时候,仍然使用未重新赋值的变量值,就好像在defer这里做了一个快照一样

多个defer是根据代码的顺序反序调用的,有点类似栈一样,后进先出

Go语言中的内置函数

append(variable,args):用来追加元素到数组、slice中,返回修改后的数组、slice
close(channel):主要用来关闭通道channel
delete(map,key):从map中删除key对应的value
panic(err_msg):触发panic从而导致程序宕机退出
recover():捕获panic
make() :用来分配内存,返回Type本身(只能应用于slice, map, channel)
new():用来分配内存,主要用来分配值类型,比如int、struct。返回指向Type的指针
cap(variable):返回某个类型的最大容量(只能用于切片和 map)
copy(slice1,,slice2):用于复制和连接slice,返回复制的数目
len(variable):返回长度,如string、array、slice、map、channel
print、println:底层打印函数,在部署环境中建议使用 fmt 包
最后编辑:
作者:qingheluo
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。