0
点赞
收藏
分享

微信扫一扫

爱上开源之golang入门至实战第四章-函数(func)(一)


前言

函数是各种编程语言不可缺少的一部分,编程的过程也就是通过函数的实现和调用来完成我们需要达到的编程的目的;把函数这个章节的内容归入到了数据类型;我一直犹豫不决; 按照一般的出牌顺序,函数就处于编程的过程,不应该纳入到数据类型里来,但是我觉得纳入到这里,能够更加明显的体现出go语言里的函数所不同的地方。 下面就听我来叨咕叨咕,golang里的函数。

爱上开源之golang入门至实战第四章-函数(func)(一)_java

 

4.4 函数

笔者在接触Golang以前,从事过多年的java程序开发;在java里函数也即为方法,就是定义好函数名,函数返回值,实现好函数体,这样就是一个函数了,例如代码(java)

[JAVA]
public void helloworld(string name){

System.out.println("Hello wolrd, " + name)

}

如上这个代码,就是一段java的代码, 代码就定义了一个函数, 函数名为helloworld,传入参数为string, 返回值为void,函数体里实现了打印的功能。 在很多的编程语言里都是这样的一个方式。 go语言的函数亦然如此, 不过go的函数有其独特的地方。

4.4.1 函数声明(定义)

语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
函数体
}

函数定义解析:

  • func:函数由 func 开始声明
  • function_name:函数名称,参数列表和返回值类型构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。

函数定义需要使用关键字func, 这个和javascript语言类似, javascript语言使用function关键字来定义一个函数; 和java等语言不使用关键字而直接声明不一样, 在go语言里,func本质上是一个类型关键字。 使用func来进行声明,本质上就是什么了一个func的对象。 对象名为function_name, 这个对象的类型是func。 所以在golang语言里, 在访问范围的允许情况下, 函数可以作为一个对象进行访问或者赋值给另外一个变量; 这个在go语言的编程里,是非常常见的场景,在go项目的源代码里看到这样的代码,大家可不要当作其他语言的语法,而觉得诧异。如下例子

func sayHello(name string) {
fmt.Println("Hello world, " + name)
}


fn1 := sayHello

if fn1 != nil {
fn1("Golang")
} else {
fmt.Println("Method is nil ")
}

==== OUTPUT ====
Hello world, Golang

在上面的代码中, 首先定义了一个sayHello的函数, 也可以理解为声明了一个名字为sayHello的函数类型的对象; 在下面的代码调用中把sayHello对象赋值给fn1, 然后判断fn1是否为nil, 如果不为nil就进行调用。

可以用type关键字定义一种指定的函数类型;如下个例子,更加的高级,同样在很多的go语言的开源项目里,都可以看到类似的写法,大家学习go语言,一定要非常熟悉这样的味道

type SayHello func(name string)

func sayHello01(name string) {
fmt.Println("Hello world 01, " + name)
}

func sayHello02(name string) {
fmt.Println("Hello world 02, " + name)
}


var sayHello SayHello

sayHello = sayHello01
sayHello("Golang")

sayHello = sayHello02
sayHello("Golang")

==== OUTPUT ====
Hello world 01, Golang
Hello world 02, Golang

在这个代码中首先定义了一个新的类型, 类型名称是SayHello, 新定义的类型是函数类型;函数类型的入参是string类型,没有返回值。

同时下面声明了两个入参是string类型,没有返回值的函数sayHello01, sayHello02; 这两个函数入参和返回值和SayHello定义的一样; 接下的调用,声明了一个SayHello函数类型的对象,然后分别把sayHello01函数对象,和sayHello02函数对象分别赋值个sayHello变量,然后进行调用;

以上的代码可以变化成如下代码

type SayHello func(name string)

var sayHello01 = SayHello(func(name string) {
fmt.Println("Hello world 01, " + name)
})

var sayHello02 = SayHello(func(name string) {
fmt.Println("Hello world 02, " + name)
})

var sayHello SayHello

sayHello = sayHello01
sayHello("Golang")

sayHello = sayHello02
sayHello("Golang")

==== OUTPUT ====
Hello world 01, Golang
Hello world 02, Golang

以上代码实际上就是将

func sayHello01(name string) {
fmt.Println("Hello world 01, " + name)
}

这样函数声明式的方式,改成了对象声明的方式

var sayHello01 = SayHello(func(name string) {
fmt.Println("Hello world 01, " + name)
})

这样的方式在很多的著名go语言开源项目里都是这样的写法,所以大家要见怪不怪,熟悉起来,这样的方式各人觉得在代码的精简度上要有优势了,当然这里是各个语言本身的编译器所决定的。

通过上面的例子里,可以看到我是使用的nil对函数对象进行判断, 对!!!,对应函数对象来说,都是指针,和map,slice一样。

大家看到了函数声明中的一大怪, 函数做对象; 函数声明中还有另一怪; 多值返回;

func function_name( [parameter list] ) [return_types] {
函数体
}

即return_types这里,大家要注意是可以多个的。上样例代码

type RequestHandler func(r http.Request, w http.ResponseWriter) (int, error)

定义了一个RequestHandler的函数类型,入口参数是Request和ResponseWriter, 返回值是int和error, 可以多个值一起返回,下面我们来看个如何调用它的例子。

type RequestHandler func(r *http.Request, w http.ResponseWriter) (int, error)

func sampleHandle(r *http.Request, w http.ResponseWriter) (int, error) {
if r == nil {
return -1, errors.New("request is nil")
}

if w == nil {
return -2, errors.New("ResponseWriter is nil")
}

return 0, nil
}

r := &http.Request{}
var w http.ResponseWriter

var handler RequestHandler
handler = sampleHandle
code, error := handler(r, w)
fmt.Printf("code=%d error-%v \n", code, error)

==== OUTPUT ====
code=-2 error-ResponseWriter is nil

结束语

本文篇幅有限,在今天的这个文章里,仅仅是golang中函数的定义声明方面,将golang在定义函数方式(对象化)和定义格式上(可多返回值)进行讲解和实例, 函数及函数调用是语言的基础和编程的核心,后面的文章,我们会接着今天的话题,继续的对golang中的函数进行讲解, 谢谢大家点赞和关注。

举报

相关推荐

0 条评论