golang如何实现“面向对象”

2025-07-09

封装:控制数据访问权限

package main

import "fmt"

type Person struct {
    name string // 私有字段
    Age  int    // 公有字段
}

// 设置私有字段的方法
func (p *Person) SetName(name string) {
    p.name = name
}

// 获取私有字段的方法
func (p *Person) GetName() string {
    return p.name
}

// 设置公有字段的方法
func (p *Person) SetAge(age int) {
    p.Age = age
}

func main() {
    p := Person{Age: 25}
    
    // 通过方法访问和修改字段
    p.SetName("Alice")
    p.SetAge(30)
    
    fmt.Println("Name:", p.GetName()) // Name: Alice
    fmt.Println("Age:", p.Age)        // Age: 30
    
    // 直接访问私有字段会导致编译错误
    // fmt.Println(p.name) // 错误:p.name未定义
}

继承:通过结构体嵌套实现

1. 简单继承示例

package main

import "fmt"

// 父结构体
type Animal struct {
    Name string
}

// 父结构体方法
func (a *Animal) Speak() {
    fmt.Println(a.Name + " makes a sound.")
}

// 子结构体
type Dog struct {
    Animal // 嵌入父结构体
}

func main() {
    dog := Dog{Animal{Name: "Buddy"}}
    dog.Speak() // 输出: Buddy makes a sound.
}

2. 方法重写示例

package main

import "fmt"

type Animal struct {
    Name string
}

func (a *Animal) Speak() {
    fmt.Println(a.Name + " makes a sound.")
}

type Dog struct {
    Animal
}

// 重写父结构体方法
func (d *Dog) Speak() {
    fmt.Println(d.Name + " barks.")
}

func main() {
    dog := Dog{Animal{Name: "Buddy"}}
    
    dog.Speak()           // 输出: Buddy barks. (重写后的方法)
    dog.Animal.Speak()   // 输出: Buddy makes a sound. (原始父类方法)
}

多态:通过接口实现

1. 简单多态示例

package main

import "fmt"

// 接口定义
type Speaker interface {
    Speak() string
}

// Dog类型实现接口
type Dog struct{}

func (d Dog) Speak() string {
    return "Woof!"
}

// Cat类型实现接口
type Cat struct{}

func (c Cat) Speak() string {
    return "Meow!"
}

// 接收接口类型参数的函数
func Introduce(s Speaker) {
    fmt.Println(s.Speak())
}

func main() {
    Introduce(Dog{}) // 输出: Woof!
    Introduce(Cat{}) // 输出: Meow!
}

2. 使用接口统一处理不同形状

package main

import "fmt"

// 形状接口
type Shape interface {
    Area() float64
}

// 矩形类型
type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// 圆形类型
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14 * c.Radius * c.Radius
}

// 通用函数处理不同形状
func PrintArea(s Shape) {
    fmt.Printf("面积: %.2f\n", s.Area())
}

func main() {
    PrintArea(Rectangle{Width: 5, Height: 3}) // 面积: 15.00
    PrintArea(Circle{Radius: 4})              // 面积: 50.24
}

3. 需要修改内部状态的多态实现

package main

import "fmt"

// 定义接口
type Animal interface {
    Speak() string
    SetName(name string)
}

// Dog实现
type Dog struct {
    name string
}

func (d *Dog) Speak() string {
    return "Woof! My name is " + d.name
}

func (d *Dog) SetName(name string) {
    d.name = name
}

func main() {
    animals := []Animal{
        &Dog{name: "Rex"},
        &Dog{name: "Buddy"},
    }
    
    for _, animal := range animals {
        fmt.Println(animal.Speak())
    }
    
    // 修改其中一个动物的名字
    animals[0].SetName("Max")
    fmt.Println(animals[0].Speak()) // Woof! My name is Max
}

接口继承

package main

import "fmt"

// 基础接口
type Animal interface {
    Speak() string
}

// 继承接口
type Mammal interface {
    Animal   // 嵌入Animal接口
    Move() string
}

// Dog实现所有接口方法
type Dog struct{}

func (d Dog) Speak() string {
    return "Woof!"
}

func (d Dog) Move() string {
    return "Runs on four legs"
}

func main() {
    var dog Dog
    
    // 使用Mammal接口
    var mammal Mammal = dog
    fmt.Println("哺乳动物:", mammal.Speak(), mammal.Move())
    
    // 也可以使用基础接口
    var animal Animal = dog
    fmt.Println("动物:", animal.Speak())
}

Go面向对象关键点总结

  1. ​封装​

    • 通过首字母大小写控制访问权限

    • 小写字母开头的字段/方法为私有

    • 大写字母开头的字段/方法为公有

  2. ​继承​

    • 使用结构体嵌套实现继承

    • 子结构体自动获得父结构体的所有字段和方法

    • 可以重写父结构体的方法

  3. ​多态​

    • 通过接口实现多态行为

    • 不同类型可以实现相同的接口

    • 以接口为参数的函数可以处理不同类型的值

  4. ​最佳实践​

    • 需要修改状态时使用指针接收者

    • 只读操作可以使用值接收者

    • 优先使用接口定义行为,而不是具体类型

    • 接口嵌套可以实现接口继承

Go语言的面向对象实现采用了独特的组合而非继承的方式,通过接口实现多态,通过结构体嵌入实现代码复用,既保持了类型系统的简洁性,又提供了强大的抽象能力。

PREV
golang的反射与断言
NEXT
golang中的defer