【go语言基础】go中的方法

先思考一个问题,什么是方法,什么是函数?

方法是从属于某个结构体或者非结构体的。在func这个关键字和方法名中间加了一个特殊的接收器类型,这个接收器可以是结构体类型的或者是非结构体类型的。从属的结构体获取该方法。

函数则没有这种从属关系。

func (t Type) methodName(parameter list) {
}
type Teacher struct {
	name     string
	salary   int
	currency string
}

// 在结构体类型上,创建一个方法并调用。
func (tea Teacher) testSalary() {
	fmt.Printf("Salary of %s is %d %s", tea.name, tea.salary, tea.currency)
}

func testUpFun() {
	tea:= Teacher{
		name:     "malou",
		salary:   10666,
		currency: "元",
	}
	tea.testSalary()
}
相同的名字的方法可以定义在不同的类型上,而相同名字的函数是不允许的
// Rectangle 定义Rectangle结构体
type Rectangle struct {
	length int
	width  int
}

// Circle 定义Circle 结构体
type Circle struct {
	radius float64
}

func (rectangle Rectangle) Area() int {
	return rectangle.width * rectangle.length
}

func (circle Circle) Area() float64 {
	return math.Pi * circle.radius * circle.radius
}

func testArea() {
	r := Rectangle{
		width:  10,
		length: 20,
	}
	fmt.Printf("Area is %d\n", r.Area())
	c := Circle{
		radius: 12,
	}
	fmt.Printf("Area is %f\n", c.Area())
}
值接收器和指针接收器之间的区别在于,在指针接收器的方法内部的改变对于调用者是可见的,然而值接收器的情况不是这样的。
// Dog struct
type Dog struct {
	name string
	age  int
}

// 使用值接收器的方法
func (d Dog) changeDogName(newName string) {
	d.name = newName
}

// 使用指针接收器的方法
func (d *Dog) changeAge(newAge int) {
	d.age = newAge
}

func testPointerStruct() {
	d := Dog{
		name: "金mao",
		age:  22,
	}
	// 并没有改变实际的值,只是改变的变量的副本
	fmt.Printf("before change is %s\n", d.name)
	d.changeDogName("马犬")
	fmt.Printf("after change is %s\n", d.name)

	// 改变的是变量本身的值
	fmt.Printf("before change is %d\n", d.age)
	d.changeAge(11)
	fmt.Printf("after change is %d\n", d.age)
}
那什么时候使用指针接收器,什么时候使用值接收器?

   指针接收器可以使用在:对方法内部的接收器所做的改变应该对调用者可见时。
   当拷贝一个结构体的代价过于昂贵的时候,比如说结构体中有很多字段,如果方法内使用
   这个结构体做为值接收器需要拷贝整个结构体,这个代价十分昂贵,这种情况下使用指针接收器,结构体不会被拷贝,只会传递一个指针到方法的内部。
   在其他的所有情况,值接收器都可以被使用。

在方法中使用值接收器 和 在函数中使用值参数:
type rectangle struct {
	width  int
	length int
}
// 函数中的参数,值类型,只能传递一个值类型
func area(r rectangle) {
	fmt.Printf("Area Function result :%d\n", r.length*r.width)
}

func (r rectangle) area() {
	fmt.Printf("Area Method result :%d\n", r.length*r.width)
}

func testFunAndMethod() {
	r := rectangle{
		width:  10,
		length: 15,
	}
	area(r)
	r.area()
	p := &r
	// (*p).area(),go解释器会自动的解引用
	p.area()
}

// 在方法中使用指针,和在函数中使用指针参数
func (r *rectangle) perimeter() {
	fmt.Printf("Area Method result is %d\n", r.width*r.length)
}

func perimeter(r *rectangle) {
	fmt.Printf("Area Function result is %d\n", r.width*r.length)
}

func testPointerStruct1() {
	r := rectangle{
		width:  12,
		length: 10,
	}
	p := &r
	perimeter(p)
	p.perimeter()

	// r.perimeter() 解释为 (&r).perimeter()  还有一种是(*p).name  相互解引用,从指针p->(*p),从值r到指针(&r)
	r.perimeter()
}

小结:

大多数方法都使用的是结构体从属,注意传递的是值传递还是指针传递。

你可能感兴趣的:(【Go】,golang,后端)