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

本文深入探讨了Go语言中slice切片和map字典的关键特性,包括len和cap的概念,append操作的机制,以及map在遍历和参数传递时的行为。通过具体的代码示例,详细分析了面试题目的正确解答,帮助读者掌握Go语言中的高级数据结构应用。
1913

被折叠的 条评论
为什么被折叠?



