亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

在 Go 中實例化類型的首選方法

在 Go 中實例化類型的首選方法

Go
狐的傳說 2021-06-18 14:27:33
我喜歡 Go 沒有給我一百萬種方法來做簡單的事情——借用 Python 之禪,“應該有一種——最好只有一種——明顯的方法來做這件事。”但是,我不清楚實例化類型的首選/慣用方式。基本類型很簡單:n := 0t := 1.5str := "Hello"但是結構呢?以下是否等價,如果是,哪個更受歡迎,為什么?var f Foo    f := Foo{}切片呢?我可以做var xs []int, xs := []int{}, or xs := make([]int),但我認為第一個選項(與結構相反)與其他選項不同?我認為這也適用于地圖。有了指針,我聽說new應該避免這種情況。這是一個很好的建議,如果是這樣,什么可以算作 的有效用法new?我意識到這在一定程度上可能是風格問題,但在任何情況下,偏好特定風格的理由都會有所幫助。
查看完整描述

3 回答

?
元芳怎么了

TA貢獻1798條經驗 獲得超7個贊

當你聲明一個變量時, whereT是某種類型:


var name T

Go 給你一塊未初始化的“歸零”內存。


對于原語,這意味著var name int它將是 0,并且var name string將是“”。在C 中,它可能被歸零,或者可能是出乎意料的。Go 保證未初始化的變量是該類型的零等價物。


在內部,切片、映射和通道被視為指針。指針零值為零,意味著它指向零內存。如果沒有初始化它,如果您嘗試對其進行操作,您可能會遇到恐慌。


該make函數是專門為切片、貼圖或通道設計的。make 函數的參數是:


make(T type, length int[, capacity int]) // For slices.

make(T[, capacity int]) // For a map.

make(T[, bufferSize int]) // For a channel. How many items can you take without blocking?

切片length是它以多少個項目開頭。容量是在需要調整大小之前分配的內存(內部,新大小 * 2,然后復制)。有關更多信息,請參閱Effective Go:使用 make 分配。


結構:new(T)等價于&T{},而不是T{}。*new(T)相當于*&T{}。


切片:make([]T,0)相當于[]T{}.


地圖:make(map[T]T)相當于map[T]T{}.


至于首選哪種方法,我問自己以下問題:


我現在知道函數內的值嗎?


如果答案是“是”,那么我會選擇上述之一T{...}。如果答案是“否”,那么我使用 make 或 new。


例如,我會避免這樣的事情:


type Name struct {

    FirstName string

    LastName string

}


func main() {

    name := &Name{FirstName:"John"}

    // other code...

    name.LastName = "Doe"

}

相反,我會做這樣的事情:


func main() {

    name := new(Name)

    name.FirstName = "John"

    // other code...

    name.LastName = "Doe"

}

為什么?因為通過使用new(Name)我明確表示我打算稍后填充這些值。如果我使用&Name{...}它就不清楚我打算稍后在同一函數中添加/更改值而不閱讀其余代碼。


當您不需要指針時,結構是例外。我將使用T{},但如果我打算添加/更改值,我不會在其中添加任何內容。當然*new(T)也有效,但這就像使用*&T{}. T{}在這種情況下更干凈,盡管我傾向于使用帶有結構的指針來避免在傳遞時進行復制。


另一件要記住的事情是, a[]*struct比 更小,調整大小更便宜[]struct,假設結構比指針大得多,指針通常為 4 - 8 個字節(64 位上為 8 個字節?)。


查看完整回答
反對 回復 2021-06-21
?
慕斯王

TA貢獻1864條經驗 獲得超2個贊

您可以查看 Go 標準庫源,在那里您可以找到許多慣用的 Go 代碼。

您是對的:var xs []int與其他兩個變體不同,因為它不“初始化”xs,xs 為零。而另外兩個確實構造了一個切片。xs := []int{}如果您需要一個零上限的空切片,則很常見,同時make為您提供更多選擇:長度和容量。另一方面,通常從一個 nil 切片開始并通過附加來填充var s []int; for ... { s = append(s, num) }

new完全無法避免,因為它是創建指針的唯一方法,例如指向 uint32 或其他內置類型。但你是對的,寫作a := new(A)是非常罕見的,主要是a := &A{}因為這可以變成a := &A{n: 17, whatever: "foo"}. 使用 ofnew并不是真的不鼓勵,但考慮到結構文字的能力,對我來說它只是 Java 的遺留物。


查看完整回答
反對 回復 2021-06-21
  • 3 回答
  • 0 關注
  • 284 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號