PHP转Go之面向对象编程,等等,Go的对象呢?

Go 肯定是面向对象的编程语言,但是在使用起来与传统的面向对象语言总是有点"独树一帜"!本文核心就是将 PHP 中常用的类、函数、继承的概念与 Go 中的做下映射

本文概要

下图对 PHP 中面向对象的一些方式与 Go 中做了简单的映射

没有的 Go,如何找到对象呢?

在 Go 中,并不存在类这个概念,写惯了 php or java 的工程师,可能对此非常不适应,Go 其实是大量借鉴 c 语言的特性,在 c/c++中,就存在结构体(struct)这个概念,类是对具有相同属性和行为对象的一个抽象,这个抽象可以称作类,自然也可以称作为结构体,新兴的语言比如Go & Rust等,都抛弃了类这个概念,而是通过扩展结构体的能力,而达到面向对象的目的。 例如:

Golang 复制代码
// persion/persion.go
package persion

type Person struct {  // 定义一个结构体,约等于 php 中的类
    Name string       // 公共变量,首字母大写
    City string       // 公共变量,首字母大写
    age  uint8        // 私有变量,首字母小写,对于私有变量仅仅是相同 package 下才可访问
}
// 这里定义了结构体的方法,同样如果以小写字母开头则表示为私有方法,外部不可访问
func (p *Person) GetName() string  { 
    return p.Name
}

func (p *Person) GetAge() uint8  {
    if p.age > 18 {
        return 18
    }
    return p.age
}

func New() *Person {
    return &Person{Name: "小能", City: "北京", age: 35}
}
// main.go
package main

import (
    "fmt"
    "persion"
)

func main()  {
    p := persion.New()
    // 可以通过变量直接访问公共变量,或者通过结构体提供的函数
    fmt.Println("姓名",p.GetName(),p.Name, "年龄", p.GetAge())
    // 私有变量仅可通过结构体暴露的方法来访问,直接访问则编译不通过
    // fmt.Println("姓名",p.Name, "年龄", p.age)  // 这一行会直接报错
}

总结:Golang 通过定义结构体,来实现了类的概念,并通过结构体内变量 or 方法首字母的大小写来控制变量和方法是 public or private

找到对象了,那如何实现对象的继承呢?

PHP 中可以通过基类(父类)和派生类(子类)的方式实现继承,Golang 中则是结构体的组合(composition)概念,即将一个结构体嵌入到另外一个结构体

Golang 复制代码
// persion/man.go
package persion

type Man struct {
    Person          // 继承了整个 Person 结构体的变量及方法
    Watch string
}

func (p *Man) GetAge() uint8 { // 重写了 GetAge 方法,作为一个 Man,没必要隐藏年龄
    return p.age
}

func NewMan() *Man {
    return &Man{
        Person: Person{        // 对于结构体复用,
            Name: "男人",
            City: "北京",
            age:  35,
        },
        Watch: "Mi Watch",
    }
}
// main.go
package main

import (
    "fmt"
    "persion"
)

func main()  {
    m := persion.NewMan()
    // output: 姓名 男人 男人 年龄 35,显然获取年龄是 Man 中定义的新方法
    fmt.Println("姓名",m.GetName(),m.Name, "年龄", m.GetAge()) 
}

那又如何实现多态呢?

在 PHP 中,多态可以借助基类和派生类来实现,除此之外,PHP 中也可以定义接口来实现多态,只需要类在实现时实现接口中定义的所有方法即可

PHP 复制代码
<?php
interface Animal {
    public function Speak();
}

class Dog implements Animal {
    public function Speak() {
        echo " 汪汪";
    }
}

class Cat implements Animal {
    public function Speak() {
        echo "喵喵";
    }
}

$dog = new Dog();
$cat = new Cat();

function animalSound(Animal $animal) {
    $animal->Speak();
}

animalSound($dog); // 输出: 汪汪
animalSound($cat); // 输出: 喵喵

同样在 Golang 中也是通过 interface 来实现多态,不过它比 PHP 语法更简约,连 implements 都省了,而是说只要你的结构体实现了对应 interface 定义的方法,默认就算是该接口的实现:

Golang 复制代码
package main
import "fmt"
// 定义一个 Animal 接口
type Animal interface {
    Speak()
}
// 定义 Dog 结构体,实现 Animal 接口
type Dog struct{}
func (d Dog) Speak() {
    fmt.Println("汪汪")
}
// 定义 Cat 结构体,实现 Animal 接口
type Cat struct{}
func (c Cat) Speak() {
    fmt.Println("喵喵")
}
func animalSound(animal Animal) {
    animal.Speak()
}
func main() {
    // 创建 Dog 和 Cat 对象
    dog := Dog{}
    animalSound(&dog)

    cat := Cat{}
    animalSound(&cat)
}

方法(Methods)和函数(Functions)的区别

需要注意的是,Golang 中跟类型关联的函数称之为方法(Methods),而函数(Functions)是完全独立的

Golang 复制代码
type Dog struct{}
func (d Dog) Speak() { // 这是方法,方法名前面指定该方法应该作用于哪种类型
    fmt.Println("汪汪")
}

经过上面的讲解你是否对 Golang 的面向对象编程有了初步的认知呢?

下一章:继续讲解下 Golang 中的函数和方法

相关推荐
Flynt1 小时前
Go 1.27 升了一波,泛型方法和 JSON v2 真香但有个坑
后端·go
lxw18449125142 小时前
PHP5、PHP7、PHP8 版本核心区别与特性
人工智能·php
AI直播技术杂谈2 小时前
直播画面突然模糊了,排查了三个小时
开发语言·php
heimeiyingwang2 小时前
【架构实战】可观测性三支柱实战:Metrics、Logging、Tracing 如何统一落地
开发语言·架构·php
用户125758524363 小时前
对象存储 URL 为什么别到处拼:后台附件预览要验这一层
后端·go·ai编程
名字还没想好☜5 小时前
Go 的 database/sql 连接池实战:SetMaxOpenConns 怎么配、连接泄漏怎么查
数据库·sql·golang·go·数据库连接池
CRMEB5 小时前
商城大促活动策划全流程:从定目标到复盘四阶段
java·开发语言·人工智能·ai·开源·php
王中阳Go6 小时前
杰富瑞实测 8 款 AI Agent,国产千问 95 分登顶:我连夜把项目的 OpenAI 硬编码全拆了
人工智能·go
新鲜势力呀7 小时前
ESP8266 物联网实战:PHP 后端 + Web 服务器实现 LED 远程控制(超详细入门教程)
前端·物联网·php
xixiaoyunya7 小时前
从零搭建跨域互联网络:个人与小团队的轻量组网方案技术解析
开发语言·智能路由器·php