Go语言中的make和new函数的区别及使用场景

401 阅读5分钟

在Go语言中,make和new是两个常用的函数,用于创建变量或数据结构。它们的使用方法和作用有一些区别,下面将详细介绍它们的使用和区别,并给出一些可能在面试中遇到的坑。

make函数

make函数用于创建切片、映射和通道等引用类型的数据结构。它的语法如下:

make(T, size)

其中,T表示切片、映射或通道的类型,size表示长度或容量。

示例1:创建一个长度为5,容量为10的整型切片

slice := make([]int, 5, 10)

示例2:创建一个长度为0,容量为5的整型切片

slice := make([]int, 0, 5)

示例3:创建一个长度为0,容量为5的映射

m := make(map[string]int, 5)

示例4:创建一个容量为10的整型通道

ch := make(chan int, 10)

make函数返回的是一个初始化后的(非零值)引用类型变量,即返回的是一个指向新分配的对象的指针。

new函数

new函数用于创建指定类型的零值对象,并返回该对象的指针。它的语法如下:

new(T)

其中,T表示要创建的类型。

示例1:创建一个整型变量的指针

var num *int
num = new(int)

示例2:创建一个结构体变量的指针

type Point struct {
    X, Y int
}
var p *Point
p = new(Point)

示例3:创建一个字符串变量的指针

var str *string
str = new(string)

new函数返回的是一个指向新分配的零值对象的指针。

make和new的区别

  • make函数只能用于创建切片、映射和通道等引用类型的数据结构,而new函数可以用于创建任意类型的变量。
  • make函数返回的是一个初始化后的(非零值)引用类型变量的指针,而new函数返回的是一个指向新分配的零值对象的指针。

在面试中,可能会遇到以下坑:

  • 有些面试官会混淆make和new的使用场景,所以在回答问题时要明确区分它们的作用和使用方法。
  • 可能会出现让你解释make和new的底层实现原理的问题,这时候你可以简单地解释它们的作用和返回值即可,不需要过于深入。
  • 面试官可能会问你make和new的使用场景和优缺点,所以在准备面试时要对它们的使用方法和区别有清晰的理解。

面试题

比如说以下面试题:

  1. make和new函数的区别是什么?

    • make函数用于创建切片、映射和通道,返回的是对应类型的初始化后的值。
    • new函数用于创建指定类型的指针,并返回指针。
  2. make函数只能用于哪些数据结构的创建?

    • make函数可以用于创建切片、映射和通道。
  3. new函数只能用于哪些类型的变量的创建?

    • new函数可以用于创建任意类型的变量,返回的是指向该类型零值的指针。
  4. make函数返回的是什么类型的值?

    • make函数返回的是对应数据结构的初始化后的值,类型为切片、映射或通道。
  5. new函数返回的是什么类型的值?

    • new函数返回的是指向指定类型零值的指针。
  6. make函数在底层是如何实现的?

    • make函数在底层会分配内存并初始化对应数据结构,然后返回初始化后的值。
  7. new函数在底层是如何实现的?

    • new函数在底层会分配内存,并返回指向该类型零值的指针。
  8. make和new函数的使用场景有哪些?

    • make函数常用于创建切片、映射和通道,并进行初始化。
    • new函数常用于创建指定类型的指针,特别是用于创建结构体变量的指针。
  9. 在创建切片时,使用make函数和new函数有什么区别?

    • 使用make函数创建切片可以指定切片的长度和容量,并进行初始化。
    • 使用new函数创建切片只会返回一个指向切片类型的指针,需要手动进行切片的初始化。
    // 使用make函数创建切片
    slice := make([]int, 5, 10)
    fmt.Println(slice) // [0 0 0 0 0]
    
    // 使用new函数创建切片
    ptr := new([]int)
    fmt.Println(ptr) // &[]
    
  10. 在创建映射时,使用make函数和new函数有什么区别?

    • 使用make函数创建映射可以进行初始化,并指定映射的初始容量。
    • 使用new函数创建映射只会返回一个指向映射类型的指针,需要手动进行映射的初始化。
    // 使用make函数创建映射
    m := make(map[string]int)
    m["a"] = 1
    fmt.Println(m) // map[a:1]
    
    // 使用new函数创建映射
    ptr := new(map[string]int)
    *ptr = make(map[string]int)
    (*ptr)["b"] = 2
    fmt.Println(*ptr) // map[b:2]
    
  11. 在创建通道时,使用make函数和new函数有什么区别?

    • 使用make函数创建通道可以指定通道的缓冲区大小,并进行初始化。
    • 使用new函数创建通道只会返回一个指向通道类型的指针,需要手动进行通道的初始化。
    // 使用make函数创建通道
    ch := make(chan int, 5)
    ch <- 1
    fmt.Println(<-ch) // 1
    
    // 使用new函数创建通道
    ptr := new(chan int)
    *ptr = make(chan int)
    *ptr <- 2
    fmt.Println(<-*ptr) // 2
    
  12. 在创建结构体变量时,使用make函数和new函数有什么区别?

    • 使用make函数无法创建结构体变量,只能用于创建切片、映射和通道。
    • 使用new函数可以创建结构体变量的指针。
    // 使用new函数创建结构体变量的指针
    type Person struct {
        Name string
        Age  int
    }
    
    ptr := new(Person)
    fmt.Println(ptr) // &{ 0}
    

总结

make和new是Go语言中常用的函数,用于创建变量或数据结构。make函数用于创建切片、映射和通道等引用类型的数据结构,返回的是一个初始化后的引用类型变量的指针;而new函数用于创建任意类型的变量,返回的是一个指向新分配的零值对象的指针。在面试中,要注意区分它们的使用场景和区别,并准备好相关的面试题。