Slice 切片
slice
的考点一般围绕着 len
,cap
,append
进行考察,我这里整理了一道面试题,基本覆盖了 slice
中的大多数考点。
题目:下面这段代码的输出结果是什么?
package main
import "fmt"
func sliceAppend(slice []int,v int) []int {
return append(slice, v)
}
func main() {
arr := make([]int,5, 10)
for i := 0;i < 5;i++ {
arr=append(arr,i)
}
slice := arr[:]
slice2 := sliceAppend(slice,1000)
slice3 := arr[:2]
slice3 = append(slice3, 10)
slice4 := arr[:8]
sliceAppend(slice4,100)
fmt.Println(arr,len(arr), cap(arr))
fmt.Println(slice,len(slice), cap(slice))
fmt.Println(slice2,len(slice2), cap(slice2))
fmt.Println(slice3,len(slice3), cap(slice3))
fmt.Println(slice4,len(slice4), cap(slice4))
}
这一题的考点比较多,我们这里总结一下相关的知识,理解了这些知识就能正确解答这道面试题。
- 在
slice
中len
和cap
时是两个完全不同的概念,len
代表了元素个数,cap
说明slice
空间可以容纳多少个元素。 - 在对
slice
进行append
操作时, 如果cap
容量足够,则直接在当前slice
后面附加上添加的值,并将len
修改为当前元素的个数。 - 如果
cap
容量不够,则重新创建一个slice
, 并将之前的slice
复制到新的slice
中然后将添加的值附加到新的slice
上。 - 当
slice
出发扩容操作时,如果之前slice
的cap
小于2048
时,每次扩容为之前容量的两倍,如果大于2048
时,则每次增加512
个 (具体数值和版本有关,大体思路一致)。
正确答案:
[0 0 10 0 100 0 1 2 3 4] 10 10
[0 0 10 0 100 0 1 2 3 4] 10 10
[0 0 0 0 0 0 1 2 3 4 1000] 11 20
[0 0 10] 3 10
[0 0 10 0] 4 10
Map 字典
map
的考点一般围绕着 range
进行考察,下面这两道面试题,基本覆盖了 map
中的大多数考点。
题目1:下面这段代码的输出结果是什么?
package main
import "fmt"
import "strconv"
type Value int
func main() {
outMap := make(map[string]Value,10)
for i := 0;i < 10;i++ {
outMap1[strconv.Itoa(i)] = Value(i)
}
for k,v range outMap {
fmt.Printf("%v: %v ", k,v)
}
fmt.Println()
}
这一题主要考察 map
在使用 range
迭代器对 map
进行遍历时的特性,即:在使用 range
遍历时的顺序时是乱序的,不能确定输出顺序。所以这一题的正确答案是输出结果不能确定。
正确答案:
输出结果不能确定
题目2:下面这段代码的输出结果是什么?
package main
import "fmt"
import "strconv"
func changeMap1(map1 map[string]Value,k string,v Value) {
map1[k] = v
}
func changeMap2(map2 map[string]*Value,k string,v Value) {
*map2[k] = v
}
type Value int
func main() {
outMap1 := make(map[string]Value,10)
for i := 0;i < 10;i++ {
outMap1[strconv.Itoa(i)] = Value(i)
}
outMap2 := make(map[string]*Value,5)
for k,v := range outMap1 {
outMap2[k] = &v
}
outMap1["5"] = 10
changeMap1(outMap1, "8",100)
*outMap2["2"] = 100
changeMap2(outMap2, "4",1000)
for i := 0;i < 10;i++ {
fmt.Printf("%v ", outMap1[strconv.Itoa(i)])
}
fmt.Println()
for i := 0;i < 10;i++ {
fmt.Printf("%v ", *outMap2[strconv.Itoa(i)])
}
fmt.Println()
}
这一题看起来代码量挺大,实际上考点还是比较少的,主要还是考察 map
作为参数的传递方式和遍历 map
需要注意的点。
知识点:
map
作为参数传递时是传递的指针,所以修改map
参数时等于修改原始变量。- 在 使用
range
迭代器对map
进行遍历时,range
会复制对象,而不是不是直接在原对象上操作。 - 在 使用
range
迭代器对map
进行遍历时,range
会复制对象,并且会重用迭代对象,所以多次遍历的对象实际上是对同一个对象进行重复赋值。
正确答案:
0 1 2 3 4 10 6 7 100 9
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000