
本文旨在帮助初学者理解 Go 语言中结构体(Struct)的使用,并将其与面向对象编程的概念相结合。通过构建一个简单的汽车(Car)示例,我们将深入探讨方法(Methods)中指针与值的区别,以及如何正确地修改结构体内部状态,从而实现预期的程序行为。
Go 语言虽然不是严格意义上的面向对象编程语言,但它提供了结构体(Struct)和方法(Methods)的概念,允许开发者以面向对象的方式组织和管理代码。本教程将通过一个汽车(Car)的例子,演示如何在 Go 语言中使用结构体来模拟对象,并解决在方法调用中遇到的值传递问题。
首先,我们定义两个结构体:Car 和 Engine。Car 结构体包含汽车的品牌(Make)、型号(Model)和一个 Engine 类型的字段。Engine 结构体包含气缸数(Cylinders)和启动状态(Started)。
package main
import (
    "fmt"
)
type Engine struct {
    Cylinders int
    Started   bool
}
type Car struct {
    Make   string
    Model  string
    Engine Engine
}接下来,我们为 Engine 结构体定义两个方法:Start() 和 IsStarted()。Start() 方法用于启动引擎,IsStarted() 方法用于检查引擎是否已启动。
立即进入“豆包AI人工智官网入口”;
立即学习“豆包AI人工智能在线问答入口”;
关键问题:指针接收者 vs. 值接收者
在 Go 语言中,方法可以有值接收者(value receiver)或指针接收者(pointer receiver)。这决定了方法是否能够修改接收者(即结构体实例)的状态。
在我们的例子中,Start() 方法需要修改 Engine 结构体的 Started 字段。因此,我们必须使用指针接收者。
func (e *Engine) Start() {
    fmt.Println("Inside the Start() func, started starts off", e.Started)
    e.Started = true
    fmt.Println("Inside the Start() func, then turns to", e.Started)
}
func (e *Engine) IsStarted() bool {
    return e.Started
}注意 Start() 和 IsStarted() 方法的接收者类型是 *Engine,而不是 Engine。
下面是完整的示例代码:
package main
import (
    "fmt"
)
type Engine struct {
    Cylinders int
    Started   bool
}
func (e *Engine) Start() {
    fmt.Println("Inside the Start() func, started starts off", e.Started)
    e.Started = true
    fmt.Println("Inside the Start() func, then turns to", e.Started)
}
func (e *Engine) IsStarted() bool {
    return e.Started
}
type Car struct {
    Make   string
    Model  string
    Engine Engine
}
func (c *Car) Start() {
    fmt.Println("starting engine ...")
    c.Engine.Start()
    fmt.Println("you'd think it would be started here ...", c.Engine)
}
func main() {
    car := Car{
        Make:  "AMC",
        Model: "Gremlin",
    }
    fmt.Printf("I'm going to work now in my %s %s\n", car.Make, car.Model)
    fmt.Println("I guess I should start my car.")
    carPtr := &car // 获取 car 的指针
    carPtr.Start()
    fmt.Println("Engine started?", car.Engine.IsStarted())
}在这个例子中,Car 结构体的 Start 方法也需要修改 Engine 结构体的状态,因此也使用了指针接收者。
运行上述代码,将得到以下输出:
I'm going to work now in my AMC Gremlin
I guess I should start my car.
starting engine ...
Inside the Start() func, started starts off false
Inside the Start() func, then turns to true
you'd think it would be started here ... {0 true}
Engine started? true可以看到,引擎成功启动,IsStarted() 方法返回 true。
Go 语言没有传统的构造函数。通常使用函数来返回结构体的实例。 可以设置默认值。
package main
import "fmt"
type Engine struct {
    Cylinders int
    Started   bool
}
func NewEngine() *Engine {
    return &Engine{
        Cylinders: 4, // 默认4缸
        Started:   false,
    }
}
type Car struct {
    Make   string
    Model  string
    Engine *Engine
}
func NewCar(make, model string) *Car {
    return &Car{
        Make:   make,
        Model:  model,
        Engine: NewEngine(), // 使用默认引擎
    }
}
func main() {
    myCar := NewCar("Toyota", "Corolla")
    fmt.Println(myCar.Engine.Cylinders) // 输出: 4
}通过本教程,我们学习了如何在 Go 语言中使用结构体和方法来模拟面向对象编程。关键在于理解指针接收者和值接收者的区别,并根据需要选择合适的接收者类型,以便正确地修改结构体的内部状态。此外,还学习了如何使用函数来初始化结构体,并设置默认值。
注意事项:
以上就是Go 语言结构体(Struct)与面向对象编程实践的详细内容,更多请关注php中文网其它相关文章!
 
                        
                        编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
 
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号