Go 语言中的 new 和 make 一直是新手比较容易混淆的东西,咋一看很相似。不过解释两者之间的不同也非常容易,下面这篇文章主要介绍了golang中make和new的区别,需要的朋友可以参考借鉴,下面来一起看看吧。
### Golang中make和new的区别详解
#### 前言
在Go语言中,`new`和`make`是两个非常重要的关键字,主要用于创建新的数据结构。然而,这两个关键字之间存在明显的区别,对于初学者来说很容易混淆。本文将详细介绍`new`与`make`的区别及其用法,并通过具体的示例来帮助理解。
#### `new` 的用法及特点
`new` 主要用于为给定的类型分配内存,并返回指向该内存的指针。`new` 的语法形式为:
```go
new(Type)
```
这里`Type`是指需要分配内存的类型。`new`函数会将分配的内存初始化为该类型的零值,并返回一个指向该内存位置的指针。例如,如果`Type`为`int`,那么零值就是0;如果`Type`为`string`,零值就是空字符串`""`。
**示例代码:**
```go
package main
import "fmt"
func main() {
// 使用new分配内存给一个int类型的变量
p1 := new(int)
fmt.Printf("p1-->%#v\n", p1) // 输出类似 (*int)(0xc42000e250)
fmt.Printf("p1 points to-->%#v\n", *p1) // 输出 0
}
```
从上面的例子可以看出,`new(int)`创建了一个指向整型的指针,并且该整型的初始值为0(整型的零值)。
#### `make` 的用法及特点
与`new`不同,`make`仅适用于三种内置的数据结构:切片(slice)、映射(map)和通道(channel)。`make`的语法形式为:
```go
make(Type, args...)
```
其中`Type`必须是上述三种类型之一,而`args`则是与这些类型相关的初始化参数。`make`不仅分配内存,还会进行初始化操作。例如,对于切片,`make`会设置其长度和容量;对于映射和通道,`make`会创建相应的内部结构。
**示例代码:**
```go
package main
import "fmt"
func main() {
// 使用make初始化一个长度为3的切片
s2 := make([]int, 3)
fmt.Printf("s2 is not nil-->%#v\n", s2) // 输出 []int{0, 0, 0}
// 使用make初始化一个空映射
m2 := make(map[int]string)
if m2 != nil {
fmt.Printf("m2 is not nil-->%#v\n", m2) // 输出 map[int]string{}
}
// 使用make初始化一个空通道
c2 := make(chan string)
if c2 != nil {
fmt.Printf("c2 is not nil-->%#v\n", c2) // 输出 (chan string)(0xc420016120)
}
}
```
以上代码展示了如何使用`make`来初始化切片、映射和通道。需要注意的是,切片的零值是`nil`,而映射和通道的零值也是`nil`。
#### `new`与`make`的主要区别
1. **适用范围不同**:`new`可以应用于任何类型,而`make`只适用于切片、映射和通道。
2. **返回类型不同**:`new`返回的是指向新分配内存的指针,而`make`返回的是初始化后的值(不是指针)。
3. **初始化方式不同**:`new`将内存初始化为该类型的零值,而`make`则根据具体的类型执行特定的初始化操作。
4. **用途不同**:`new`主要用于创建类型的基本实例,而`make`用于创建复杂类型如切片、映射和通道的实例。
#### 实战应用案例
为了更直观地理解`new`与`make`的区别,我们来看几个实际的应用案例:
**修改切片元素**
```go
func modifySlice(s []int) {
s[0] = 1
}
func main() {
s2 := make([]int, 3)
fmt.Printf("%#v\n", s2) // 输出 []int{0, 0, 0}
modifySlice(s2)
fmt.Printf("%#v\n", s2) // 输出 []int{1, 0, 0}
}
```
在这个例子中,可以看到`modifySlice`函数能够直接修改由`make`创建的切片的元素。
**修改映射元素**
```go
func modifyMap(m map[int]string) {
m[0] = "string"
}
func main() {
m2 := make(map[int]string)
modifyMap(m2)
fmt.Println(m2) // 输出 map[0:string]
}
```
同样的,通过`make`创建的映射也可以在函数内部被修改。
**总结**
虽然`new`和`make`都可用于分配内存,但它们在适用范围、返回类型以及初始化方式等方面存在明显差异。掌握这两种关键字的正确使用方法,有助于更好地编写高效、清晰的Go程序。
- 1
- 2
前往页