每次学习并整理一个Golang的知识点,每天进步一点点。今天由slice的一道题引起类型系统的知识点🤔。

代码片段

观察如下代码片段,判断能否编译通过;如果可以,写出输出结果?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"

func add(l []int) []int {
	l = append(l, 10)
	return l
}

func modify(l []int) []int {
	l[0] = 1
	return l
}
func main() {
	a := []int{7, 8, 9}
	add(a)
	fmt.Println(a)
	modify(a)
	fmt.Println(a)
	fmt.Println(append(a, 10))

}

思考后看答案…

思考后看答案


答疑解惑

输出结果如下:

1
2
3
[7 8 9]
[1 8 9]
[1 8 9 10]

同样是参数传递切片类型,append操作会导致底层数组重新分配内存,add方法中会创建新切片,所以main函数中的a在调用add后并没有被改变;而修改切片会修改切片的底层数据内容,所以会影响原切片。

你做对了吗?😊

其他相关答案,欢迎在评论区留言补充!

拓展阅读

Go语言中的大多数类型都基于值语义,包括:

  • 基本类型,如byte、int、bool、float32、float64和string等;
  • 复合类型,如数组(array)、结构体(struct)和指针(pointer)等。

而channel和map类似,本质上是一个指针。将它们设计为引用类型而不是统一的值类型的原因是,完整复制一个channel或map并不是常规需求。

值语义和引用语义的差别

值语义和引用语义的差别在于赋值,比如下面的例子:

1
2
b = a
b.Modify()

如果b的修改不会影响a的值,那么此类型属于值类型。如果会影响a的值,那么此类型是引用类型。在Go中所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作。

需要特别注意的是,Go语言中的数组(array)和基本类型没有区别,是很纯粹的值类型(value type)。如果将数组作为函数的参数类型,则在函数调用时该参数将发生数据复制。因此,在函数体中无法修改传入的数组的内容,因为函数内操作的只是所传入数组的一个副本。

例如:

1
2
3
4
var a = [3]int{1, 2, 3}
var b = a
b[1]++
fmt.Println(a, b)

该程序的运行结果如下:

[1 2 3] [1 3 3]

这表明b=a赋值语句是数组内容的完整复制。要想表达引用,需要用指针:

1
2
3
4
var a = [3]int{1, 2, 3}
var b = &a
b[1]++
fmt.Println(a, *b)

该程序的运行结果如下:

[1 3 3] [1 3 3]

这表明b=&a赋值语句是数组内容的引用。变量b的类型不是[3]int,而是*[3]int类型。

append两数组切片

append数组切片,直接将一个数组切片追加到另一个数组切片的末尾,可以用如下方法:

1
2
3
mySlice := []int{1, 2, 3}
mySlice2 := []int{8, 9, 10}
mySlice = append(mySlice, mySlice2...)

需要注意的是,我们在第二个参数mySlice2后面加了三个点,即一个省略号,如果没有这个省略号,会有编译错误,因为按append()的语义,从第二个参数起的所有参数都是待附加的元素。因为mySlice中的元素类型为int,所以直接传递mySlice2肯定是行不通的。加上省略号相当于把mySlice2包含的所有元素打散后传入

上面的调用等同于:

mySlice = append(mySlice, 8, 9, 10)

下期提问

观察如下代码片段,写出你认为的正确答案?

  1. 关于字符串连接,下面语法正确的是:()

    • A. str := 'abc' + '123'
    • B. str := "abc" + "123"
    • C. str := '123' + "abc"
    • D. fmt.Sprintf("abc%d", 123)
  2. 下面赋值正确的是:()

    • A. var x = nil
    • B. var x interface{} = nil
    • C. var x string = nil
    • D. var x error = nil

答案及解析将在下期文章中给出,欢迎大家在评论区留言,独乐乐不如众乐乐,交流学习,互相进步。


欢迎转发和评论。更多优质原创文章,欢迎关注微信公众号“IYue爱月”或扫描下方二维码:

xujpxm_qrcode_gh