✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/UWz06📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
11. Go 语言当中 new 的作用是什么?
在 Go 语言中,new 是一个内置函数,用于创建一个新的零值变量并返回该变量的指针。new 的语法如下:
new(T)
其中,T 表示要创建的变量类型。new 返回一个指向新变量的指针,该变量的值为其类型的零值。在 Go 语言中,每个变量都有一个类型和一个值,而 new 可以用于创建变量的指针。
new 的作用在于在堆上分配内存空间,而不是在栈上分配。使用 new 函数创建变量时,返回的指针指向在堆上分配的变量,即使该变量在函数调用结束后仍然存在。因此,new 通常用于创建结构体、数组和其他复杂数据类型的指针。
需要注意的是,new 只能创建变量的指针,而不能用于创建变量本身。如果需要创建变量本身,可以使用变量声明语句,如下所示:
var x T
其中,T 表示变量类型,x 是变量名。
12. Go 语言中 make 的作用是什么?
在 Go 语言中,make 是一个内置函数,用于创建一些特定类型的数据结构,如 slice、map 和 channel 等。make 的语法如下:
make(T, args...)
其中,T 表示要创建的数据结构的类型,args 表示该数据结构的初始化参数,如长度、容量等。具体来说,make 的作用如下:
-
创建 slice:make([]T, length, capacity),其中 T 表示 slice 的元素类型,length 表示 slice 的长度,capacity 表示 slice 的容量。
-
创建 map:make(map[T]U, capacity),其中 T 表示 map 的键类型,U 表示 map 的值类型,capacity 表示 map 的容量。
-
创建 channel:make(chan T, capacity),其中 T 表示 channel 中元素的类型,capacity 表示 channel 的缓冲区大小,如果 capacity 为 0,则表示该 channel 是无缓冲的。
需要注意的是,使用 make 函数创建的数据结构是分配在堆上的,并返回一个引用,即一个指向数据结构的指针。这与使用 new 函数创建变量的方式不同,因为 new 只分配了变量所需的内存空间,而 make 分配了变量所需的内存空间,并初始化了变量的其他属性。因此,make 更适用于创建 slice、map 和 channel 等复杂的数据结构。
13. Go 内置函数 make 和 new 的区别?
首先纠正下 make 和 new 是内置函数,不是关键字。
变量初始化,一般包括 2 步,变量声明 + 变量内存分配,var 关键字就是用来声明变量的,new 和 make 函数主要是用来分配内存的。
var 声明值类型的变量时,系统会默认为他分配内存空间,并赋该类型的零值。
比如布尔、数字、字符串、结构体。
如果指针类型或者引用类型的变量,系统不会为它分配内存,默认就是 nil
。此时如果你想直接使用,那么系统会抛异常,必须进行内存分配后,才能使用。
new 和 make 两个内置函数,主要用来分配内存空间,有了内存,变量就能使用了,主要有以下 2 点区别:
1. 使用场景区别
- make 只能用来分配及初始化类型为 slice、map、chan 的数据。
-
new 可以分配任意类型的数据,并且置零。
2. 返回 值区别
-
make 函数原型如下,返回的是 slice、map、chan 类型本身。
这 3 种类型是引用类型,就没有必要返回他们的指针。
func make(t Type, size ...IntegerType) Type
-
new 函数原型如下,返回一个指向该类型内存地址的指针。
func new(Type) *Type
14. Printf(),Sprintf(),FprintF() 都是格式化输出,有什么不同?
在 Go 语言中,Printf()、Sprintf() 和 FprintF() 都是用于格式化输出的函数,但它们有一些不同之处,具体如下:
1. Printf()
Printf() 是最常用的格式化输出函数,它将格式化后的字符串输出到标准输出流(一般是终端窗口)。Printf() 的语法如下:
Printf(format string, a ...interface{}) (n int, err error)
其中,format 表示要输出的格式化字符串,a ...interface{} 表示要格式化的参数列表,可以是任意类型的参数。Printf() 函数会根据格式化字符串中的格式说明符将参数格式化为指定格式,并输出到标准输出流中。
2. Sprintf()
Sprintf() 与 Printf() 的作用类似,不同的是,它将格式化后的字符串输出到一个字符串中,而不是标准输出流。Sprintf() 的语法如下:
Sprintf(format string, a ...interface{}) string
其中,format 和 a ...interface{} 的含义与 Printf() 相同,但 Sprintf() 返回一个字符串,而不是将格式化后的字符串输出到标准输出流中。
3. FprintF()
FprintF() 与 Printf() 的作用也类似,不同的是,它将格式化后的字符串输出到指定的文件中,而不是标准输出流。FprintF() 的语法如下:
FprintF(w io.Writer, format string, a ...interface{}) (n int, err error)
其中,w 表示要输出的文件,可以是 os.Stdout、os.Stderr 或其他实现了 io.Writer 接口的类型。format 和 a ...interface{} 的含义与 Printf() 相同。FprintF() 会将格式化后的字符串输出到指定的文件中。
综上所述,Printf()、Sprintf() 和 FprintF() 都是格式化输出函数,它们的作用有所不同,但都可以通过格式说明符将参数格式化为指定格式。需要根据具体的需求选择不同的函数来使用。
15. Golang 的参数传递、引用类型
在 Golang 中,函数调用时参数传递可以分为值传递和引用传递。
值传递:将参数的值复制一份,然后将复制的值传递给函数,函数对参数的修改不会影响到原始的值。常见的值类型如 int、float、bool 等都是值类型,它们的传递都是值传递。
引用传递:将参数的地址复制一份,然后将复制的地址传递给函数,函数对参数的修改会影响到原始的值。常见的引用类型如 Slice、Map、Channel、指针等都是引用类型,它们的传递都是引用传递。
需要注意的是,在 Golang 中数组虽然是引用类型,但是它的传递却是值传递。这是因为 Golang 的数组长度是固定的,数组的值复制时会将整个数组的元素都复制一遍,因此传递数组时的开销较大,而且数组的长度也不可变,因此将数组的地址复制一份也无法修改原数组的长度,所以 Golang 采用了值传递的方式。
总之,对于值类型的参数,使用值传递即可;对于引用类型的参数,使用引用传递可以避免大量数据的复制,提高程序的效率。同时,在使用引用类型的参数时,需要注意并发访问的问题。