乐趣区

关于go:Go-快速入门指南-make-和-new

概述

new() 函数为数据类型 T 调配一块内存,初始化为类型 T 的零值,返回类型为指向数据的指针,能够用于所有数据类型。

make() 函数除了为数据类型 T 分配内存外,还能够指定长度和容量,返回类型为数据的初始化构造,只限于 切片 , Map, 通道

make

什么时候用

申明并初始化 切片, Map, 通道(前面会讲到)。

为什么定义

为什么专门针对切片, Map 和 通道类型定义一个 make 函数呢?
因为这 3 种数据类型要求应用时必须实现初始化,未初始化就应用可能会引发谬误,具体规定如下:

  • 未初始化的切片值为 nil, 如果间接获取或设置元素数据会报错
  • 未初始化的 Map 值为 nil, 如果间接设置元素数据会报错
  • 未初始化的 通道 值为 nil, 发送数据和接收数据会阻塞 (详情在前面通道章节介绍)

未初始化的切片

package main

func main() {var s []int

    // 间接获取值: 报错
    _ = s[0]

    // 间接设置值: 同样报错
    //s[0] = 100
}

// $ go run main.go
// 输入如下 
/**
panic: runtime error: index out of range [0] with length 0
...
exit status 2
*/

未初始化的 Map

package main

func main() {var m map[int]string

    // 间接设置值: 报错
    m[100] = "hello world"
}

// $ go run main.go
// 输入如下 
/**
panic: panic: assignment to entry in nil map
...
exit status 2
*/

append()

为什么切片即便是 nil, 却能够调用 append() 函数呢? 因为 append() 函数外部实现中做了兼容,如果切片为 nil
那么会先申请好须要的内存空间,而后在复制给切片,等于 笼罩掉原来的切片,这样就不会报错了。

应用 new 初始化切片和 Map

如果咱们不应用 make() 函数创立切片和 Map 能够吗?当然是能够的,new()
函数能够创立任何数据类型,当然也包含切片和 Map
然而 new() 函数返回的指针指向的是类型的 零值,对于切片和 Map 来说,零值仍然是 nil, 这又回到了下面的问题。

new() 创立的切片

package main

import "fmt"

func main() {s := new([]int)

    fmt.Printf("s type = %T, val = %#v\n", *s, *s)

    // 间接获取值: 报错
    _ = (*s)[0]

    // 间接设置值: 同样报错
    //s[0] = 100
}

// $ go run main.go
// 输入如下 
/**
s type = []int, val = []int(nil)
panic: runtime error: index out of range [0] with length 0
...
exit status 2
*/

new() 创立的 Map

package main

import "fmt"

func main() {m := new(map[int]string)

    fmt.Printf("s type = %T, val = %#v\n", *m, *m)

    // 间接设置值: 报错
    (*m)[100] = "hello world"
}

// $ go run main.go
// 输入如下 
/**
m type = map[int]string, val = map[int]string(nil)
panic: assignment to entry in nil map
...
exit status 2
*/

new

什么时候用

除了 切片, Map, 通道(前面会讲到) 以外的其余数据类型。

小结

初始化 切片 , Map, 通道 三种数据类型时,应用 make() 函数,初始化其余数据类型时,应用 new() 函数。

分割我

退出移动版