Go – 方法

作者: 太阳上的雨天 分类: Go 发布时间: 2022-02-22 10:02

方法

1. 方法的声明

在函数声明时,在其名字之前加一个变量,既是一个方法。

Example:

package demo

// 声明一个正方形结构体
//x, y坐标
type Square struct {
    x int
    y int
}

//声明一个方法计算Square 的面积
func (s Square) Area() int {
    return s.x * s.y
}

(下面这段话出自于 《Go语言圣经》)

在上面的代码中,参数s 叫做方法的接受器(receiver),在早期的面相对象语言中将调用一个方法称为“向一个对象发送消息”。

在Go语言中我们可以任意的选择接受器的名字。但是由于经常会被用到,习惯建议用其类型的第一个字母。如Square的s,作为接受器。

2. Receiver的类型

一般分为两种类型。一种是指针类型,一种是非指针类型(如上的代码)。

指针类型,还是以上面Square为例

Example:

package demo

// 声明一个正方形结构体
//x, y坐标
type Square struct {
    x int
    y int
}

//声明一个方法计算Square 的面积
func (s *Square) Area() int {
    return s.x * s.y
}

区别?如何选择?

在解释区别之前,先说下函数的参数。

当调用一个函数时,会对其每一个参数值进行拷贝,如果一个函数需要更新一个变量,或者函数的其中一个参数是在太大,希望能够避免进行这种默认的拷贝,这个时候我们就需要用到指针了。出自于 《Go语言圣经》

Note:其实非指针类型也可以更新变量。因为原始对象和拷贝对象只是一个别名而已,实际上他们指向的对象使一样的。修改非指针类型拷贝后的对象也可以修改变量。

如何选择:

  1. 不管method的receiver是指针类型还是非指针类型,都是可以通过指针/非指针类型进行调用的,因为编译器会做类型的转换处理
  2. 声明一个method的receiver该是指针类型还是非指针类型的时候,只需要考虑两个因素:
    • 这个对象本身是不是特别大,如果特别大建议声明成指针类型,因为非指针类型会进行一次拷贝
    • 如果用指针类型作为receiver,一定要注意,指针类型指向的始终是一块儿内存地址。就算对其进行了拷贝,也是指向同一内存地址。

嵌入结构体类型来扩展类型

先来个Example再解释:

package main

//Animal 动物
type Animal struct {
    Name string
    Food map[string]interface{}
}

//Dog 狗
type Dog struct {
    Animal
    PetName string // 爱称 比如:大哥、坦克、子弹等等
}

上面代码就是嵌入结构体类型

如果只看这句话,很难理解到底什么意思。就好像其他编程语言面向对象类的继承。比如PHP、JAVA的子类通过关键字extends继承了父类(注意其实按照类的继承来理解是错误的,并不等价。这里只是为了便于理解

Java

public class Animal {

    static String Name;
    static HashMap<String, Object> Food;

}

public class Dog extends Animal{

    static String PetName;

    public static void main(String[] args) {

        System.out.println(PetName);

        System.out.println(Name);
        System.out.println(Food);

    }
}

PHP

class Animal {

    protected $name;

    protected $food;

}

class Dog extends Animal {

    private $petName;

    public function test() {

        var_dump($this->petName) . PHP_EOL;
        var_dump($this->name) . PHP_EOL;
        var_dump($this->food) . PHP_EOL;

    }

}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注