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

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

t=&T{} 和 t=new(T) 的核心區(qū)別是什么

t=&T{} 和 t=new(T) 的核心區(qū)別是什么

Go
慕田峪4524236 2022-05-05 18:02:33
似乎使用所有“0”成員值創(chuàng)建新對(duì)象指針的兩種方法都返回一個(gè)指針:type T struct{}...t1:=&T{}t2:=new(T)那么 t1 和 t2 之間的核心區(qū)別是什么,或者有什么“新”可以做而 &T{} 不能做的事情,反之亦然?
查看完整描述

3 回答

?
海綿寶寶撒

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

[...] 有什么“新”可以做而 &T{} 不能做的事情,反之亦然?

我能想到三個(gè)不同點(diǎn):

  • “復(fù)合文字”語(yǔ)法(的T{}一部分&T{})僅適用于“結(jié)構(gòu)、數(shù)組、切片和映射”[鏈接],而該new函數(shù)適用于任何類型[鏈接]。

  • 對(duì)于結(jié)構(gòu)或數(shù)組類型,new函數(shù)始終為其元素生成零值,而復(fù)合文字語(yǔ)法允許您根據(jù)需要將某些元素初始化為非零值。

  • 對(duì)于切片或映射類型,new函數(shù)始終返回指向 的指針nil,而復(fù)合文字語(yǔ)法始終返回已初始化的切片或映射。(對(duì)于地圖來(lái)說(shuō),這非常重要,因?yàn)槟荒芟?. 中添加元素nil。)此外,復(fù)合字面量語(yǔ)法甚至可以創(chuàng)建空切片或地圖。

(第二個(gè)和第三個(gè)要點(diǎn)實(shí)際上是同一件事的兩個(gè)方面——new函數(shù)總是創(chuàng)建零值——但我將它們分開(kāi)列出,因?yàn)椴煌愋偷暮x有點(diǎn)不同。)


查看完整回答
反對(duì) 回復(fù) 2022-05-05
?
肥皂起泡泡

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

見(jiàn)ruak 的回答。不過(guò),我想指出一些內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。你不應(yīng)該在生產(chǎn)代碼中使用它們,但它們有助于闡明幕后真正發(fā)生的事情,在 Go 運(yùn)行時(shí)。


本質(zhì)上,切片由三個(gè)值表示。包reflect導(dǎo)出一個(gè)類型,SliceHeader:


SliceHeader 是切片的運(yùn)行時(shí)表示。它不能安全或便攜地使用,它的表示可能會(huì)在以后的版本中發(fā)生變化。此外,Data 字段不足以保證它引用的數(shù)據(jù)不會(huì)被垃圾收集,因此程序必須保留一個(gè)單獨(dú)的、正確類型的指向底層數(shù)據(jù)的指針。


type SliceHeader struct {

        Data uintptr

        Len  int

        Cap  int

}

如果我們使用它來(lái)檢查類型變量[]T(對(duì)于任何類型T),我們可以看到三個(gè)部分:指向底層數(shù)組的指針、長(zhǎng)度和容量。在內(nèi)部,切片值v始終具有所有這三個(gè)部分。我認(rèn)為應(yīng)該保持一個(gè)一般條件,如果你不使用unsafe它來(lái)打破它,通過(guò)檢查它似乎會(huì)保持(無(wú)論如何基于有限的測(cè)試):


該Data字段不為零(在這種情況下Len,并且Cap可以但不必非零),或者

該Data字段為零(在這種情況下Len和Cap都應(yīng)該為零)。

如果該字段為零,則該切片值v是。nilData


通過(guò)使用unsafe包裝,我們可以故意破壞它(然后將其全部放回原處——希望在我們破壞它的同時(shí)不會(huì)出現(xiàn)任何問(wèn)題),從而檢查碎片。當(dāng)Go Playground 上的這段代碼運(yùn)行時(shí)(下面也有一個(gè)副本),它會(huì)打?。?/p>


via &literal: base of array is 0x1e52bc; len is 0; cap is 0.

Go calls this non-nil.


via new: base of array is 0x0; len is 0; cap is 0.

  Go calls this nil even though we clobbered len() and cap()

  Making it non-nil by unsafe hackery, we get [42] (with cap=1).


after setting *p1=nil: base of array is 0x0; len is 0; cap is 0.

  Go calls this nil even though we clobbered len() and cap()

  Making it non-nil by unsafe hackery, we get [42] (with cap=1).

代碼本身有點(diǎn)長(zhǎng),所以我把它留到最后(或使用上面的 Playground 鏈接)。但它表明p == nil源代碼中的實(shí)際測(cè)試僅編譯為對(duì)該Data字段的檢查。


當(dāng)你這樣做時(shí):


p2 := new([]int)

該new函數(shù)實(shí)際上只分配切片頭。它將所有三個(gè)部分設(shè)置為零并返回指向結(jié)果標(biāo)頭的指針。因此*p2,其中包含三個(gè)零字段,這使其成為正確的nil值。


另一方面,當(dāng)你這樣做時(shí):


p1 := &[]int{}

Go 編譯器構(gòu)建一個(gè)空數(shù)組(大小為零,保持零整數(shù)),然后構(gòu)建一個(gè)切片頭:指針部分指向空數(shù)組,長(zhǎng)度和容量設(shè)置為零。然后p1使用非零Data字段指向此標(biāo)頭。稍后的賦值*p1 = nil將零寫(xiě)入所有三個(gè)字段。


讓我用粗體字重復(fù)一遍:這些不是語(yǔ)言規(guī)范所承諾的,它們只是實(shí)際的實(shí)現(xiàn)。


地圖的工作方式非常相似。map 變量實(shí)際上是一個(gè)指向map header的指針。map headers 的細(xì)節(jié)比 slice headers 更難訪問(wèn):它們沒(méi)有reflect類型。實(shí)際實(shí)現(xiàn)可在此處type hmap查看(請(qǐng)注意,它未導(dǎo)出)。


這意味著m2 := new(map[T1]T2)實(shí)際上只分配一個(gè)指針,并將該指針本身設(shè)置為 nil。沒(méi)有實(shí)際的地圖!該new函數(shù)返回 nil 指針,然后m2是nil. 同樣,只需在tovar m1 map[T1]T2中設(shè)置一個(gè)簡(jiǎn)單的指針值。但是分配一個(gè)實(shí)際的結(jié)構(gòu),填充它,并指出它。我們可以再次窺視 Go Playground 的幕后,使用不保證明天可以工作的代碼,看看它的效果。m1nilvar m3 map[T1]T2{}hmapm3


作為編寫(xiě) Go 程序的人,你不需要知道這些。但是,如果您使用過(guò)低級(jí)語(yǔ)言(例如匯編和 C),這些可以解釋很多。特別是,這些解釋了為什么不能插入到 nil 映射中:映射變量本身保存一個(gè)指針值,并且在映射變量本身有一個(gè)指向(可能為空的)映射頭的非零指針之前,沒(méi)有辦法做插入。插入可以分配一個(gè)新映射并插入數(shù)據(jù),但映射變量不會(huì)指向正確的hmap標(biāo)頭對(duì)象。


(語(yǔ)言作者可以通過(guò)使用第二級(jí)間接來(lái)完成這項(xiàng)工作:映射變量可以是指向指向映射頭的變量的指針?;蛘咚麄兛梢允褂成渥兞渴冀K指向頭,并new實(shí)際上分配了一個(gè)標(biāo)頭,方式make是這樣;那么永遠(yuǎn)不會(huì)有一個(gè) nil 映射。但是他們沒(méi)有做這些,我們得到了我們得到的,這很好:你只需要知道初始化映射。)


這是切片檢查器。(使用操場(chǎng)鏈接查看地圖檢查器:鑒于我必須將hmap' 的定義從運(yùn)行時(shí)復(fù)制出來(lái),我希望它特別脆弱且不值得展示。切片頭的結(jié)構(gòu)似乎不太可能隨著時(shí)間而改變。 )


package main


import (

    "fmt"

    "reflect"

    "unsafe"

)


func main() {

    p1 := &[]int{}

    p2 := new([]int)

    show("via &literal", *p1)

    show("\nvia new", *p2)

    *p1 = nil

    show("\nafter setting *p1=nil", *p1)

}


// This demonstrates that given a slice (p), the test

//    if p == nil

// is really a test on p.Data.  If it's zero (nil),

// the slice as a whole is nil.  If it's nonzero, the

// slice as a whole is non-nil.

func show(what string, p []int) {

    pp := unsafe.Pointer(&p)

    sh := (*reflect.SliceHeader)(pp)

    fmt.Printf("%s: base of array is %#x; len is %d; cap is %d.\n",

        what, sh.Data, sh.Len, sh.Cap)

    olen, ocap := len(p), cap(p)

    sh.Len, sh.Cap = 1, 1 // evil

    if p == nil {

        fmt.Println("  Go calls this nil even though we clobbered len() and cap()")

        answer := 42

        sh.Data = uintptr(unsafe.Pointer(&answer))

        fmt.Printf("  Making it non-nil by unsafe hackery, we get %v (with cap=%d).\n",

            p, cap(p))

        sh.Data = 0 // restore nil-ness

    } else {

        fmt.Println("Go calls this non-nil.")

    }

    sh.Len, sh.Cap = olen, ocap // undo evil

}


查看完整回答
反對(duì) 回復(fù) 2022-05-05
?
FFIVE

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

對(duì)于結(jié)構(gòu)和其他復(fù)合材料,兩者都是相同的。


t1:=&T{}

t2:=new(T)

//Both are same

您不能在不使用new. 您需要?jiǎng)?chuàng)建一個(gè)命名變量,然后獲取其地址。


func newInt() *int {            

    return new(int)                 

}               


func newInt() *int {

    // return &int{} --> invalid

    var dummy int

    return &dummy

}


查看完整回答
反對(duì) 回復(fù) 2022-05-05
  • 3 回答
  • 0 關(guān)注
  • 173 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號(hào)

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