doumengbai2031 2013-06-15 16:04
浏览 39
已采纳

Go中的OO样式结构对象

I'm very new to Go and I've read (from the FAQ) that Go is both OO and not. I'd like to create data structures using Structs and find myself trying to think of Structs as simple objects. My canonical proof of concept is building a Car. I understand that a car is a real world object so it lends itself to OOP, which might be weird in Go. But I imagine that a User class would be equally convenient so this will be a useful learning exercise and reference for me.

This example compiles but does not function properly. It uses multiple source files so you'll have to manipulate your GOPATH and create a project folder for this.

It should look like this:

$GOPATH/src/car/car.go
$GOPATH/src/car/parts/engine.go

Or another way to look at it:

$ cd /tmp/go/src
$ tree 
.
└── car
    ├── car.go
    └── parts
        └── engine.go

Main asks the car instance to .Start() below. When it comes back to main, car is not started.

/* car/car.go */
package main

import (
    "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
", 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
}

Splitting up the source files is convenient. All of this works

/* car/parts/engine.go */
package parts

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
}

Running this outputs:

$ go run car.go
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? false

Calling functions on the structs makes sense but I wonder if I'm trying to manipulate internal state in the wrong way? Or maybe I don't understand scopes. If someone could help me through this, I'd value it greatly for reference.

Also if someone has a preferred or idiomatic method for initializers. For example, the engine might default to 4 cylinders.

  • 写回答

2条回答 默认 最新

  • dsiftnc99059 2013-06-15 22:12
    关注

    Methods

    Pointers vs. Values

    The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers. This is because pointer methods can modify the receiver; invoking them on a copy of the value would cause those modifications to be discarded.

    Therefore, for your Engine Start method to work, use a pointer receiver, since the method modifies the receiver. For example,

    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())
    }
    

    Output:

    false
    Inside the Start() func, started starts off false
    Inside the Start() func, then turns to true
    true
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog