本文旨在幫助 Go 語(yǔ)言初學(xué)者理解如何使用結(jié)構(gòu)體(Struct)模擬面向?qū)ο缶幊?/a>(OOP)中的對(duì)象,并通過(guò)構(gòu)建一個(gè)簡(jiǎn)單的 Car 示例,深入探討值接收者和指針接收者的區(qū)別,以及如何在 Go 中正確地修改結(jié)構(gòu)體內(nèi)部狀態(tài),提供初始化結(jié)構(gòu)體的常用方法。
在 Go 語(yǔ)言中,雖然沒(méi)有像 Java 或 Python 那樣的類(Class)的概念,但我們可以使用結(jié)構(gòu)體(Struct)來(lái)定義數(shù)據(jù)結(jié)構(gòu),并結(jié)合方法(Methods)來(lái)實(shí)現(xiàn)類似面向?qū)ο缶幊痰墓δ?。本文將通過(guò)一個(gè) Car 的例子,深入講解如何在 Go 中使用結(jié)構(gòu)體,以及如何正確地操作結(jié)構(gòu)體的內(nèi)部狀態(tài)。
在 Go 語(yǔ)言中,方法可以有值接收者(Value Receiver)或指針接收者(Pointer Receiver)。這兩種接收者在方法調(diào)用時(shí)有著重要的區(qū)別,尤其是在修改結(jié)構(gòu)體內(nèi)部狀態(tài)時(shí)。
值接收者
當(dāng)方法使用值接收者時(shí),方法內(nèi)部操作的是結(jié)構(gòu)體的一個(gè)副本。這意味著對(duì)結(jié)構(gòu)體內(nèi)部狀態(tài)的修改不會(huì)影響原始結(jié)構(gòu)體。
指針接收者
當(dāng)方法使用指針接收者時(shí),方法內(nèi)部操作的是結(jié)構(gòu)體的指針,可以直接修改原始結(jié)構(gòu)體的內(nèi)容。
在提供的 Car 示例中,Engine 結(jié)構(gòu)體的 Start() 方法最初使用的是值接收者:
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) } func (engine Engine) IsStarted() bool { return engine.started }
由于 Start() 方法使用值接收者,因此在 Start() 方法內(nèi)部修改 engine.started 的值,實(shí)際上修改的是 engine 的副本,而不是原始的 engine 結(jié)構(gòu)體。因此,在 main() 函數(shù)中調(diào)用 car.Start() 后,car.engine.IsStarted() 仍然返回 false。
解決方案:使用指針接收者
要解決這個(gè)問(wèn)題,需要將 Engine 結(jié)構(gòu)體的 Start() 方法改為使用指針接收者:
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) } func (engine *Engine) IsStarted() bool { return engine.started }
通過(guò)使用指針接收者 *Engine,Start() 方法可以直接修改原始的 Engine 結(jié)構(gòu)體,從而使 car.engine.IsStarted() 返回 true。
修改 Car 結(jié)構(gòu)體和 main 函數(shù)
即構(gòu)數(shù)智人是由即構(gòu)科技推出的AI虛擬數(shù)字人視頻創(chuàng)作平臺(tái),支持?jǐn)?shù)字人形象定制、短視頻創(chuàng)作、數(shù)字人直播等。
同時(shí),為了使代碼正常運(yùn)行,需要修改 Car 結(jié)構(gòu)體,使其包含 Engine 結(jié)構(gòu)體的指針,并在 main 函數(shù)中正確初始化 Engine。
package main import ( "car/parts" "fmt" ) type Car struct { sMake string model string engine *parts.Engine // 使用 Engine 的指針 } func main() { engine := &parts.Engine{cylinders: 4, started: false} // 初始化 Engine car := Car{ sMake: "AMC", model: "Gremlin", engine: engine, // 賦值 Engine 指針 } 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()) // success -- engine started is true :) } 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 }
相應(yīng)的 parts/engine.go 文件內(nèi)容:
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 }
Go 語(yǔ)言提供了多種初始化結(jié)構(gòu)體的方式。
直接初始化
car := Car{ sMake: "AMC", model: "Gremlin", }
這種方式可以指定結(jié)構(gòu)體字段的值。
使用 new() 函數(shù)
car := new(Car) car.sMake = "AMC" car.model = "Gremlin"
new() 函數(shù)會(huì)分配內(nèi)存并返回指向該內(nèi)存的指針。
使用構(gòu)造函數(shù)(Constructor)
雖然 Go 語(yǔ)言沒(méi)有構(gòu)造函數(shù)的概念,但我們可以自定義函數(shù)來(lái)初始化結(jié)構(gòu)體。
func NewCar(make, model string) *Car { return &Car{ sMake: make, model: model, } } // 使用 car := NewCar("AMC", "Gremlin")
構(gòu)造函數(shù)可以提供更靈活的初始化邏輯,例如設(shè)置默認(rèn)值或執(zhí)行其他初始化操作。
本文通過(guò)一個(gè) Car 的例子,詳細(xì)講解了如何在 Go 語(yǔ)言中使用結(jié)構(gòu)體模擬面向?qū)ο缶幊?,重點(diǎn)介紹了值接收者和指針接收者的區(qū)別,以及如何正確地修改結(jié)構(gòu)體的內(nèi)部狀態(tài)。此外,還介紹了結(jié)構(gòu)體的多種初始化方式。希望本文能夠幫助 Go 語(yǔ)言初學(xué)者更好地理解結(jié)構(gòu)體的使用,并能夠在實(shí)際項(xiàng)目中靈活運(yùn)用。
以上就是Go 結(jié)構(gòu)體(Struct)與面向?qū)ο缶幊?/a>:構(gòu)建 Car 示例詳解的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
編程怎么學(xué)習(xí)?編程怎么入門?編程在哪學(xué)?編程怎么學(xué)才快?不用擔(dān)心,這里為大家提供了編程速學(xué)教程(入門課程),有需要的小伙伴保存下載就能學(xué)習(xí)啦!
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號(hào)
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)