新功能和未初始化变量的区别是什么?两者的优点是什么?
s := new(string) // *string
var s *string // *string
var s string // string
这只是为了简化代码吗?因为我认为它是相同的
s := new(string) /* same as */ var s *string = &emptyString
答案 0 :(得分:4)
此代码:
var s *string
只需将“s”声明为指向字符串的指针即可。在这种情况下,“s”是一个nil指针,这是指针golang中的默认值。
此代码:
s := new(string)
还将“s”声明为指向字符串的指针,但这次是初始化字符串。这意味着“s”是一个非零指针,并指向golang中一个空字符串的字符串的默认值。
答案 1 :(得分:2)
第一个区别:
内置函数new采用类型T,为a分配存储空间 该类型的变量在运行时
第二个差异:
new
将已分配的字符串初始化为空字符串(“”)并初始化指向此字符串地址的指针,但var ptr2 *string
只需将ptr2
初始化为nil
,并且不分配任何字符串:
示例代码A(带注释输出):
ptr := new(string) // *ptr has value "", ptr: static type *string
fmt.Println(len(*ptr)) // 0
fmt.Println(cap([]byte(*ptr))) // 32
fmt.Printf("%T %q\n", ptr, *ptr) // *string ""
示例代码B(带注释输出):
var ptr2 *string // ptr2 has value nil, static type *string
fmt.Printf("%T %#[1]v\n", ptr2) // *string (*string)(nil)
//fmt.Println(len(*ptr2)) // panic: runtime error: invalid memory address or nil pointer dereference
//fmt.Println(cap([]byte(*ptr2)))
示例代码C(带注释输出):
var str string // str has value "", static type string
fmt.Println(len(str)) // 0
fmt.Println(cap([]byte(str))) // 32
fmt.Printf("%T %[1]q\n", str) // string ""
分配:
内置函数new采用类型T,为a分配存储空间 运行时该类型的变量,并返回类型* T的值 指着它。该变量按照中所述进行初始化 关于initial values的部分。
new(T)
例如
type S struct { a int; b float64 } new(S)
为S类变量分配存储空间,对其进行初始化(a = 0, b = 0.0),并返回包含地址的类型* S的值 位置。
参考:https://golang.org/ref/spec
使用新分配:
Go有两个分配原语,内置 新功能和制作。他们做不同的事情并适用于 不同的类型,可能会令人困惑,但规则很简单。 我们来谈谈新的第一个。 这是一个分配的内置函数 记忆,但与其他语言中的同名不同 初始化内存,它只将它归零。也就是说,new(T)分配 为类型为T的新项目归零存储并返回其地址,a 类型* T的值。在Go术语中,它返回一个指向新术语的指针 分配了类型为T的零值。
由于new返回的内存为零,因此安排很有帮助 在设计数据结构时,每种类型的零值 无需进一步初始化即可使用。这意味着用户 数据结构可以创建一个新的和正确的工作。对于 例如,bytes.Buffer的文档声明“零 Buffer的值是一个可以使用的空缓冲区。“同样, sync.Mutex没有显式构造函数或Init方法。 相反,sync.Mutex的零值被定义为未锁定 互斥。
零价值有用的属性可以传递。考虑一下 类型声明。
type SyncedBuffer struct { lock sync.Mutex buffer bytes.Buffer } Values of type SyncedBuffer are also ready to use immediately upon allocation or just declaration. In the next snippet, both p and v
无需进一步安排即可正常使用:
p := new(SyncedBuffer) // type *SyncedBuffer var v SyncedBuffer // type SyncedBuffer
使用make进行分配:返回分配。内置功能 make(T,args)的用途与new(T)不同。它创建 切片,地图和通道,它返回一个初始化(不是 归零)T类型的值(不是* T)。区别的原因是 这三种类型代表了数据的引用 必须在使用前初始化的结构。一片,例如, 是一个三项描述符,包含指向数据的指针(在 数组),长度和容量,直到那些项目 初始化后,切片为零。对于切片,地图和通道,make 初始化内部数据结构并为其准备值 使用。例如,
make([]int, 10, 100)
分配一个100个整数的数组,然后创建一个切片结构 长度10,容量100 指向数组的前10个元素。 (制作切片时, 容量可以省略;请参阅切片部分了解更多信息 信息。)相反,new([] int)返回一个新的指针 分配的归零片结构,即指向nil片的指针 值。这些示例说明了new和make之间的区别:
var p *[]int = new([]int) // allocates slice structure; *p == nil; rarely useful var v []int = make([]int, 100) // the slice v now refers to a new array of 100 ints // Unnecessarily complex: var p *[]int = new([]int) *p = make([]int, 100, 100) // Idiomatic: v := make([]int, 100)
请记住,make仅适用于地图,切片和通道 不返回指针。获取使用new分配的显式指针 或明确地获取变量的地址。