第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會有你想問的

golang 資源所有權(quán)模式(文件、連接、關(guān)閉)

golang 資源所有權(quán)模式(文件、連接、關(guān)閉)

Go
不負(fù)相思意 2023-08-07 14:56:25
在 golang 中管理資源所有權(quán)的正確方法是什么?假設(shè)我有以下內(nèi)容:db, err := sql.Open("mysql", "role@/test_db")am := NewResourceManager(db)am.DoWork()db.Close()總是讓調(diào)用函數(shù)維護(hù)關(guān)閉資源的所有權(quán)和責(zé)任是典型的嗎?這對我來說有點(diǎn)奇怪,因?yàn)殛P(guān)閉后,仍然保留引用,如果我或其他人稍后不小心,am可以嘗試使用(我想這是延遲的情況;但是,如果我想將 ResourceManager 傳回)從這個(gè)塊開始,我如何正確推遲文件的關(guān)閉?我實(shí)際上希望它在這個(gè)塊完成執(zhí)行時(shí)保持打開狀態(tài))。我發(fā)現(xiàn)在其他語言中,我經(jīng)常希望允許實(shí)例管理資源,然后在調(diào)用析構(gòu)函數(shù)時(shí)清理它,就像這個(gè)玩具 python 示例:dbamclass Writer():   def __init__(self, filename):       self.f = open(filename, 'w+')   def __del__(self):       self.f.close()   def write(value):       self.f.write(value)不幸的是,golang 中沒有析構(gòu)函數(shù)。除了這樣的事情之外,我不確定如何在 go 中做到這一點(diǎn):type ResourceManager interface {   DoWork()   // Close() ?}type resourceManager struct {  db *sql.DB}func NewResourceManager(db *sql.DB) ResourceManager {  return &resourceManager{db}} db, err := sql.Open("mysql", "role@/test_db")am := NewResourceManager(db)am.DoWork()am.Close()  // using method shortening但這似乎不太透明,而且我不確定如何傳達(dá) ResourceManager 現(xiàn)在也需要 Close() 的信息。我發(fā)現(xiàn)這是一個(gè)常見的絆腳石,即我還想要一個(gè)保存 gRPC 客戶端連接的資源管理器,如果這些類型的資源不是由資源管理對象管理的,那么我的主要功能似乎是充斥著大量的資源管理,即打開和關(guān)閉。例如,我可以想象一種情況,我不想main知道有關(guān)該對象及其資源的任何信息:...func NewResourceManager() ResourceManager {  db, err := sql.Open("mysql", "role@/test_db")  return &resourceManager{db}}...// main elsewheream := NewResourceManager()am.DoWork()
查看完整描述

1 回答

?
溫溫醬

TA貢獻(xiàn)1752條經(jīng)驗(yàn) 獲得超4個(gè)贊

您選擇了一個(gè)不好的示例,因?yàn)槟ǔ赜脭?shù)據(jù)庫連接,而不是每次使用時(shí)打開和關(guān)閉一個(gè)數(shù)據(jù)庫連接。因此,您可以將數(shù)據(jù)庫連接傳遞給使用它的函數(shù),并在調(diào)用者中進(jìn)行資源管理,而不需要資源管理器:


// Imports etc omitted for the sake of readability


func PingHandler(db *sql.DB) http.Handler (

? ? return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

? ? ? ?if err := db.ping(); err != nil {

? ? ? ? ? http.Error(w,e.Error(),500)

? ? ? ?}

? ? })

)


func main(){

? ? db,_ := sql.Open("superdb",os.Getenv("APP_DBURL"))


? ? // Note the db connection will only be closed if main exits.

? ? defer db.Close()


? ? // Setup the server

? ? http.Handle("/ping", PingHandler(db))

? ? server := &http.Server{Addr: ":8080"}


? ? // Create a channel for listening on SIGINT, -TERM and -QUIT

? ? stop := make(chan os.Signal, 1)


? ? // Register channel to be notified on said signals

? ? signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)


? ? go func(){

? ? ? ? ? ? // When we get the signal...

? ? ? ? ? ? <- stop

? ? ? ? ? ? ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)

? ? ? ? ? ? // ... we gracefully shut down the server.

? ? ? ? ? ? // That ensures that no new connections, which potentially

? ? ? ? ? ? // would use our db connection, are accepted.

? ? ? ? ? ? if err := server.Shutdown(ctx); err != nil {

? ? ? ? ? ? ? ? // handle err

? ? ? ? ? ? }

? ? }


? ? // This blocks until the server is shut down.

? ? // AFTER it is shut down, main exits, the deferred calls are executed.

? ? // In this case, the database connection is closed.

? ? // And it is closed only after the last handler call which uses the connection is finished.

? ? // Mission accomplished.

? ? server.ListenAndServe()

}

因此,在這個(gè)示例中,不需要資源管理器,而且老實(shí)說,我想不出真正需要資源管理器的示例。在極少數(shù)情況下,我需要類似的東西,我使用了sync.Pool.

但是,對于 gRPC 客戶端連接,也無需維護(hù)池:

[...]但是,ClientConn 應(yīng)該自行管理連接,因此如果連接斷開,它將自動重新連接。如果您有多個(gè)后端,則可以連接到其中多個(gè)后端并在它們之間實(shí)現(xiàn)負(fù)載平衡。[...]

因此,同樣的原則適用:創(chuàng)建一個(gè)連接(池),根據(jù)需要傳遞它,確保在完成所有工作后關(guān)閉它。

不要將資源管理隱藏在其他地方,而是盡可能靠近使用資源的代碼并盡可能明確地管理資源。


查看完整回答
反對 回復(fù) 2023-08-07
  • 1 回答
  • 0 關(guān)注
  • 154 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號