为了账号安全,请及时绑定邮箱和手机立即绑定

Go 中的 OO 风格结构对象

Go 中的 OO 风格结构对象

Go
白衣非少年 2021-06-16 22:14:40
我对 Go 很陌生,我读过(从常见问题解答)Go 既是面向对象又不是面向对象。我想使用 Structs 创建数据结构,并发现自己试图将 Structs 视为简单的对象。我的规范概念证明是制造汽车。我知道汽车是现实世界的对象,因此它适用于 OOP,这在 Go 中可能很奇怪。但我认为 User 类同样方便,因此这对我来说将是一个有用的学习练习和参考。此示例可编译但无法正常运行。它使用多个源文件,因此您必须操作 GOPATH 并为此创建一个项目文件夹。它应该是这样的:$GOPATH/src/car/car.go$GOPATH/src/car/parts/engine.go或者另一种看待它的方式:$ cd /tmp/go/src$ tree .└── car    ├── car.go    └── parts        └── engine.goMain 要求汽车实例下面的 .Start() 。当它回到 main 时,汽车没有启动。/* car/car.go */package mainimport (    "car/parts"    "fmt")type Car struct {    sMake  string    model  string    engine parts.Engine}func init() { // optional init of package    // note that we can't use this as a constructor?}func main() {    car := Car{        sMake: "AMC",        model: "Gremlin",    }    fmt.Printf("I'm going to work now in my %s %s\n", car.sMake, car.model)    fmt.Println("I guess I should start my car.")    car.Start()    fmt.Println("Engine started?", car.engine.IsStarted())    // fail -- engine started is false  :(}func (car Car) Start() {    fmt.Println("starting engine ...")    car.engine.Start()    fmt.Println("you'd think it would be started here ...", car.engine)    // but it's not}拆分源文件很方便。所有这些都有效/* car/parts/engine.go */package partsimport (    "fmt")type Engine struct {    cylinders int    started   bool}func (engine Engine) Start() {    fmt.Println("Inside the Start() func, started starts off", engine.started)    engine.started = true    fmt.Println("Inside the Start() func, then turns to", engine.started)    // this is a sanity check}func (engine Engine) IsStarted() bool {    return engine.started}运行此输出:$ go run car.goI'm going to work now in my AMC GremlinI guess I should start my car.starting engine ...Inside the Start() func, started starts off falseInside the Start() func, then turns to trueyou'd think it would be started here ... {0 true}Engine started? false在结构上调用函数是有道理的,但我想知道我是否试图以错误的方式操纵内部状态?或者也许我不了解范围。如果有人可以帮助我解决这个问题,我会非常重视它以供参考。此外,如果有人对初始值设定项有首选或惯用的方法。例如,发动机可能默认为 4 缸。
查看完整描述

2 回答

?
冉冉说

TA贡献1877条经验 获得超1个赞

方法


指针与值

关于接收者的指针与值的规则是值方法可以在指针和值上调用,但指针方法只能在指针上调用。这是因为指针方法可以修改接收者;在值的副本上调用它们将导致这些修改被丢弃。


因此,要使您的Engine Start方法工作,请使用指针接收器,因为该方法会修改接收器。例如,


package main


import (

    "fmt"

)


type Engine struct {

    cylinders int

    started   bool

}


func (engine *Engine) Start() {

    fmt.Println("Inside the Start() func, started starts off", engine.started)

    engine.started = true

    fmt.Println("Inside the Start() func, then turns to", engine.started)

    // this is a sanity check

}


func (engine *Engine) IsStarted() bool {

    return engine.started

}


func main() {

    var engine Engine

    fmt.Println(engine.IsStarted())

    engine.Start()

    fmt.Println(engine.IsStarted())

}

输出:


false

Inside the Start() func, started starts off false

Inside the Start() func, then turns to true

true


查看完整回答
反对 回复 2021-06-21
?
红糖糍粑

TA贡献1815条经验 获得超6个赞

您正在通过value传递接收器。改为通过指针传递:


func (engine *Engine) Start() {

             ^

}


查看完整回答
反对 回复 2021-06-21
  • 2 回答
  • 0 关注
  • 177 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信