关于golang:Go-语言中的一等公民看似普通的函数凭什么

10次阅读

共计 2625 个字符,预计需要花费 7 分钟才能阅读完成。

若有任何问题或倡议,欢送及时交换和碰撞。我的公众号是【脑子进煎鱼了】,GitHub 地址:https://github.com/eddycjy。

大家好,我是煎鱼。

在 Go 语言中,一提函数,大家提的最多的就是“Go 语言的函数是一等公民”。这个定义来的十分忽然,咱们先理解一下什么是一等公民。

依据维基百科的一等公民(First-class citizen)的定义:

In programming language design, a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, modified, and assigned to a variable.

在编程语言设计中,给定编程语言中的一等公民(也就是类型,对象,实体或值)能够把函数赋值给变量,也能够把函数作为其它函数的参数或者返回值来间接应用。

Go 语言的函数也满足这个定义,因而常被称为“一等公民”。理解分明背景后,接下来进一步开展。

一般函数

在 Go 语言中一般函数的定义格局为 func [函数名](入参)(出参),如下:

func callFuncA(x, y string) (s string, err error) {return x + y, nil}

func main() {callFuncA("炸", "煎鱼")
}

在示例代码中申明了一个函数名为 callFuncA 的办法,他只容许在包内调用,因而首字母为小写。

其具备两个入参,别离是 xy,类型都为 string。而出参为变量 serr,类型别离为 stringerror

另外在函数体内返回值时,也能够采纳快捷返回的形式:

func callFuncA(x, y string) (s string, err error) {
    s = x + y
    return
}

在出参时所申明的变量名称,是能够利用到本身函数的。因而若间接执行 return 则会隐式返回曾经申明的出参变量。

在函数定义时,其入参还反对可变参数的语法:

func callFuncA(x ...string) (s string, err error) {s = strings.Join(x, ",")
    return
}

func main() {fmt.Println(callFuncA("炸", "煎鱼"))
}

在入参变量上申明为 x ...string,则示意变量 xstring 类型的可变变量,可能在入参时传入多个 string 参数。

可变变量所传入的格局为切片(slice)类型,该类型咱们会在前面的章节进行解说,你能够了解为不受长度限度的动静数组:

[0: 炸 1: 煎鱼]

个别对可变变量的常见后续操作多是循环遍历解决,又或是进行拼接等操作。

匿名函数

Go 语言也默认反对匿名函数的申明,申明的形式与一般函数简直一样:

func main() {s := func(x, y string) (s string, err error) {return x + y, nil}

    s("炸", "煎鱼")
}

匿名函数能够在任意中央申明,且不须要定义函数名,如果在函数体后马上跟 () 则示意申明后立刻执行:

func main() {s, _ := func(x, y string) (s string, err error) {return x + y, nil}("炸", "煎鱼")
}

而在所有的函数类应用中,有一点十分重要,那就是函数变量作用域的了解:

func main() {
    x, y := "炸", "煎鱼"
    s, _ := func() (s string, err error) {return x + y, nil}()
    fmt.Println(s)
}

该匿名函数没有形参,函数外部没有定义相应的变量,此时其读取的是全局的 xy 变量的值,输入后果是“炸煎鱼”。

func main() {
    x, y := "炸", "煎鱼"
    _, _ = func(x, y string) (s string, err error) {
        x = "吃"
        return x + y, nil
    }(x, y)
    fmt.Println(x, y)
}

该匿名函数无形参,然而在函数外部又从新赋值了变量 x。那么最终内部所输入的变量 x 的值是什么呢?输入后果是“炸 煎鱼”。

为什么明明在函数内曾经对变量 x 从新赋值,却仍然没有扭转全局变量 x 的值呢?

其本质起因是作用域不同,函数外部所批改的变量 x 是函数内的局部变量。而内部的是全局的变量,所归属的作用域不同。

构造办法

在联合构造体(struct)的形式下,能够申明归属于该构造体下的办法:

type T struct{}

func NewT() *T {return &T{}
}

func (t *T) callFuncA(x, y string) (s string, err error) {return x + y, nil}

func main() {NewT().callFuncA("炸", "煎鱼")
}

具体的函数的应用办法与一般函数一样,无其余区别。

而与构造体无关的值传递、援用传递的办法调用将在具体前面的章节再开展。

内置函数

Go 语言自身有反对一些内置函数,这些内置函数的调用不须要援用第三方规范库。内置函数的作用是用于配合 Go 语言的惯例应用,数量非常少。如下:

  • 用于获取某些类型的长度和容量:len、cap。
  • 用于创立并调配某些类型的内存:new、make。
  • 用于错误处理机制(异样恐慌、异样捕捉):panic、recover。
  • 用于复制和新增切片(slice):copy、append。
  • 用于简略输入信息:print、println。
  • 用于解决复数:complex、real、imag。

针对每个内置函数的实在应用场景,咱们会在后续的章节再进一步开展,因为每个内置函数实质上都对应着各类型的应用场景。

总结

在本章节中,咱们介绍了 Go 语言的函数为什么称是一等公民,并且针对函数的各类变形:一般函数、匿名函数、构造办法、内置函数进行了根本的阐明。

面对新手入门最容易犯错的函数作用域问题,也进行了根本的梳理。这块倡议大家要多多深刻思考、了解,防止日后踩坑。

我的公众号

分享 Go 语言、微服务架构和奇怪的零碎设计,欢送大家关注我的公众号和我进行交换和沟通。

最好的关系是相互成就 ,各位的 点赞 就是煎鱼创作的最大能源,感激反对。

正文完
 0