Go slice literal和make slice在行为上有区别吗?

Go slice literal和make slice在行为上有区别吗?,go,slice,Go,Slice,注意:没有回答我的问题,因为这比较了切片声明和生成切片,而我的问题比较了切片文本和生成切片。这个问题的答案很简单,因为裸片声明创建了一个nil片,但是,如果您仔细阅读下面的问题,我根本不会创建nil片 有两种方法可以创建切片并附加到切片。下面的代码显示了示例1和示例2的两种方式 主程序包 进口( “fmt” ) func main(){ //例1 a:=[]整数{} fmt.Printf(“第(a)节:%d;第(a)节:%d;第(a)节:%v\n”,第(a)节,第(a)节,第(a)节) a=附加

注意:没有回答我的问题,因为这比较了切片声明和生成切片,而我的问题比较了切片文本和生成切片。这个问题的答案很简单,因为裸片声明创建了一个nil片,但是,如果您仔细阅读下面的问题,我根本不会创建nil片

有两种方法可以创建切片并附加到切片。下面的代码显示了示例1和示例2的两种方式

主程序包
进口(
“fmt”
)
func main(){
//例1
a:=[]整数{}
fmt.Printf(“第(a)节:%d;第(a)节:%d;第(a)节:%v\n”,第(a)节,第(a)节,第(a)节)
a=附加(a、10、20、30、40、50)
fmt.Printf(“第(a)节:%d;第(a)节:%d;第(a)节:%v\n”,第(a)节,第(a)节,第(a)节)
//例2
b:=make([]整数,0)
fmt.Printf(“第(b)节:%d;第(b)节:%d;第(b)节:%v\n”,第(b)节,第(b)节,第(b)节)
b=附加(b,10,20,30,40,50)
fmt.Printf(“第(b)节:%d;第(b)节:%d;第(b)节:%v\n”,第(b)节,第(b)节,第(b)节)
}
输出:

len(a): 0; cap(a): 0; a: []
len(a): 5; cap(a): 6; a: [10 20 30 40 50]
len(b): 0; cap(b): 0; b: []
len(b): 5; cap(b): 6; b: [10 20 30 40 50]

使用
[]int{}
make([]int,0)
创建空切片的两种方法是否等效?他们在行为上有什么不同吗?

我稍微修改了你的例子

//示例1
a:=[]整数{}
pa:=&a
//例2
b:=make([]整数,0)
pb:=&b
runtime.KeepAlive(pa)
runtime.KeepAlive(pb)
它的汇编目的是:

*** main.go#12   >    a := []int{}
0x4e56a9    488d0538bb1100          lea rax, ptr [runtime.zerobase]
0x4e56b0    4889442470          mov qword ptr [rsp+0x70], rax
0x4e56b5    8400                test byte ptr [rax], al
0x4e56b7    eb00                jmp 0x4e56b9
0x4e56b9    4889842418010000        mov qword ptr [rsp+0x118], rax
0x4e56c1    0f57c0              xorps xmm0, xmm0
0x4e56c4    0f11842420010000        movups xmmword ptr [rsp+0x120], xmm0
*** main.go#13   >    pa := &a
0x4e56cc    488d842418010000        lea rax, ptr [rsp+0x118]
0x4e56d4    4889442460          mov qword ptr [rsp+0x60], rax
*** main.go#16   >    b := make([]int, 0)
0x4e56d9    488d0520020100          lea rax, ptr [__image_base__+1005824]
0x4e56e0    48890424            mov qword ptr [rsp], rax
0x4e56e4    0f57c0              xorps xmm0, xmm0
0x4e56e7    0f11442408          movups xmmword ptr [rsp+0x8], xmm0
0x4e56ec    e8bf49f6ff          call $runtime.makeslice
0x4e56f1    488b442418          mov rax, qword ptr [rsp+0x18]
0x4e56f6    4889842400010000        mov qword ptr [rsp+0x100], rax
0x4e56fe    0f57c0              xorps xmm0, xmm0
0x4e5701    0f11842408010000        movups xmmword ptr [rsp+0x108], xmm0
*** main.go#17   >    pb := &b
0x4e5709    488d842400010000        lea rax, ptr [rsp+0x100]
0x4e5711    4889442458          mov qword ptr [rsp+0x58], rax

似乎
make([]int,0)
导致堆分配(通过
$runtime.makeslice()
),但不深入显示
makeslice()
也返回基于
&zerobase
的片:

    if size == 0 {
        return unsafe.Pointer(&zerobase)
    }

因此,这两个代码段都提供了相同的切片结构,其中数据指针设置为
zerobase

我稍微修改了您的示例

//示例1
a:=[]整数{}
pa:=&a
//例2
b:=make([]整数,0)
pb:=&b
runtime.KeepAlive(pa)
runtime.KeepAlive(pb)
它的汇编目的是:

*** main.go#12   >    a := []int{}
0x4e56a9    488d0538bb1100          lea rax, ptr [runtime.zerobase]
0x4e56b0    4889442470          mov qword ptr [rsp+0x70], rax
0x4e56b5    8400                test byte ptr [rax], al
0x4e56b7    eb00                jmp 0x4e56b9
0x4e56b9    4889842418010000        mov qword ptr [rsp+0x118], rax
0x4e56c1    0f57c0              xorps xmm0, xmm0
0x4e56c4    0f11842420010000        movups xmmword ptr [rsp+0x120], xmm0
*** main.go#13   >    pa := &a
0x4e56cc    488d842418010000        lea rax, ptr [rsp+0x118]
0x4e56d4    4889442460          mov qword ptr [rsp+0x60], rax
*** main.go#16   >    b := make([]int, 0)
0x4e56d9    488d0520020100          lea rax, ptr [__image_base__+1005824]
0x4e56e0    48890424            mov qword ptr [rsp], rax
0x4e56e4    0f57c0              xorps xmm0, xmm0
0x4e56e7    0f11442408          movups xmmword ptr [rsp+0x8], xmm0
0x4e56ec    e8bf49f6ff          call $runtime.makeslice
0x4e56f1    488b442418          mov rax, qword ptr [rsp+0x18]
0x4e56f6    4889842400010000        mov qword ptr [rsp+0x100], rax
0x4e56fe    0f57c0              xorps xmm0, xmm0
0x4e5701    0f11842408010000        movups xmmword ptr [rsp+0x108], xmm0
*** main.go#17   >    pb := &b
0x4e5709    488d842400010000        lea rax, ptr [rsp+0x100]
0x4e5711    4889442458          mov qword ptr [rsp+0x58], rax

似乎
make([]int,0)
导致堆分配(通过
$runtime.makeslice()
),但不深入显示
makeslice()
也返回基于
&zerobase
的片:

    if size == 0 {
        return unsafe.Pointer(&zerobase)
    }

因此,这两个代码段提供了相同的切片结构,其中数据指针设置为
zerobase

,链接的问题依次链接到相关文档:。TL;DR:x:=[]int{}和
x:=make([]int,0)
之间没有功能上的区别。你是对的。我说错了
x:=[]int{}
make([]int,0)
相同。不过,您声称的区别并不存在。@Flimzy如果
x:=[]int{}
make([]int,0)
相同,那么这个问题的答案是正确的。这一事实在相关问题中没有讨论。发布一个问题的答案,解释两者是相同的,这不是很好吗?@Volker在这里看一下Go规范:golang.org/ref/spec。如果您将其导出为PDF,您将获得84页。它有25000多字。我不知道你的情况,但我肯定不能在一小时内阅读25000字的技术文档!关于这个主题,这里有一个很好的答案:链接的问题依次链接到相关文档:。TL;DR:x:=[]int{}和
x:=make([]int,0)
之间没有功能上的区别。你是对的。我说错了
x:=[]int{}
make([]int,0)
相同。不过,您声称的区别并不存在。@Flimzy如果
x:=[]int{}
make([]int,0)
相同,那么这个问题的答案是正确的。这一事实在相关问题中没有讨论。发布一个问题的答案,解释两者是相同的,这不是很好吗?@Volker在这里看一下Go规范:golang.org/ref/spec。如果您将其导出为PDF,您将获得84页。它有25000多字。我不知道你的情况,但我肯定不能在一小时内阅读25000字的技术文档!关于这个问题,这里有一个很好的答案:它们在语义上是等价的。您的示例中的转义分析不同这一事实不能保证是一致的,并且在语言规范中没有依据。@JimB发现案例在分配方面是等效的,我编辑了答案。@maxim_ge感谢您提供了详细的答案。这很好地回答了我的问题。我建议您编辑答案,删除您之前得出的错误结论,只写正确的结论。这将使你的答案更清晰,更容易阅读。它们在语义上是等价的。您的示例中的转义分析不同这一事实不能保证是一致的,并且在语言规范中没有依据。@JimB发现案例在分配方面是等效的,我编辑了答案。@maxim_ge感谢您提供了详细的答案。这很好地回答了我的问题。我建议您编辑答案,删除您之前得出的错误结论,只写正确的结论。这将使你的答案更清楚,更容易阅读。