函数与方法

函数

函数的格式:func+函数名+ 参数 + 返回值(可选) + 函数体

例如:

func myfunction( a, b int) (int) {
    
}

在Go中,函数被看作第一类值(first-class values),函数像其他值一样,拥有类型,可以被赋值给其他变量,传递给函数,从函数返回。函数类型的零值是nil。

在golang中还有两个特殊的函数,main函数和init函数。

main函数作为一个程序的入口,只能有一个。

func main() {

}

init函数在每个package是可选的,可有可无,甚至可以有多个,init函数在你导入该package时程序会自动调用init函数,所以init函数不用我们手动调用,并且它只会被调用一次,因此当一个package被多次引用时,它只会被导入一次。

func init() {  

}  

方法

方法能给用户自定义的类型添加新的行为。

例如:

type myInt int

func (a myInt) add(b myInt) myInt { 
    return a + b
}

方法和函数的区别在于方法有一个接收者,给一个函数添加一个接收者,那么它就变成了方法。接收者可以是值接收者,也可以是指针接收者

Golang 不是一个纯粹的面向对象的编程语言,它不支持类。因此通过在一个类型上建立方法来实现与 class 相似的行为。

同名方法可以定义在不同的类型上,但是 Golang 不允许同名函数。假设有两个结构体 Square 和 Circle。在 Square 和 Circle 上定义同名的方法是合法的。

值接收者与指针接收者区别

先看下面的例子

定义一个Employee的结构体

type Employee struct {
    name string
    age  int
}

值接收者:

func (e Employee) changeName(newName string) {
    fmt.Printf("changeName: address %p\n", &e)
    e.name = newName
}

指针接收者:

func (e *Employee) changeAge(newAge int) {
    fmt.Printf("changeAge: address %p\n", e)
    e.age = newAge
}

main函数:

func main() {

	emOne := &Employee{
		name: "em1",
		age:  18,
	}
	fmt.Printf("before emOne: %v, address: %p\n", emOne, emOne)
	emOne.changeName("em1_change")
	emOne.changeAge(19)
	fmt.Printf("after emOne: %v, address: %p\n", emOne, emOne)

	emTwo := Employee{
		name: "em2",
		age:  18,
	}
	fmt.Printf("before emTwo: %v, address: %p\n", emTwo, &emTwo)
	emTwo.changeName("emTwo_change")
	emTwo.changeAge(20)
	fmt.Printf("after emTwo: %v, address: %p\n", emTwo, &emTwo)
}

执行结果:

before emOne: &{em1 18}, address: 0xc000004480
changeName: address 0xc0000044e0
changeAge: address 0xc000004480
after emOne: &{em1 19}, address: 0xc000004480

before emTwo: {em2 18}, address: 0xc000004520
changeName: address 0xc000004560
changeAge: address 0xc000004520
after emTwo: {em2 20}, address: 0xc000004520

通过以上结果可以看出:

  • 对于值接收者,如果调用者也是值对象,那么会将调用者的值拷贝一份,并执行方法,方法的调用不会影响到调用者值。 如果调用者是指针对象,那么会解引用指针对象为值,然后将解引的对象拷贝一份,然后执行方法。

  • 对于指针接收者,如果调用者是值对象,会使用值的引用来调用方法。如果调用者是指针对象,实际上也是“传值”,方法里的操作会影响到调用者,类似于指针传参,拷贝了一份指针,但是指针指向同一个对象。

使用指针作为方法的接收者的理由:

  • 方法能够修改接收者指向的值。
  • 避免在每次调用方法时复制该值,在值的类型为大型结构体时,这样做会更加高效。

版权声明:本文为weixin_45804031原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。