Skip to content

array, slice 题目 #47

Open
Open
@JasonJe

Description

@JasonJe
  1. 判断下面代码能否通过编译
func main() {
   s1 := []int{123}
   s2 := []int{45}
   s1 = append(s1s2)
   fmt.Println(s1)
}

解析:append的第二个参数不能直接使用slice,需要使用...操作符,将一个切片追加到另一个切片上,或者直接跟上元素append(s1, 1, 2, 3)

  1. 以下代码的输出是什么
func main() {
	a := []int{7, 8, 9}
	fmt.Printf("%+v\n", a)
	ap(a)
	fmt.Printf("%+v\n", a)
	app(a)
	fmt.Printf("%+v\n", a)

}

func ap(a []int) {
	a = append(a, 10)
}

func app(a []int) {
	a[0] = 1
}

输出:

[7, 8, 9]
[7, 8, 9]
[1, 8, 9]

解析:append导致底层数组重新分配了内存,ap中的a的底层数组与外部的a不是同一个,并未改变外部的。

  1. 切片的截取操作符
package main

import (  
    "fmt"
)

func main() {  
    a := [5]int{1, 2, 3, 4, 5}
    t := a[3:4:4]
    fmt.Println(t[0])
}

解析:假设一个底层数组a的大小是n,截取切片的操作是a[i: j],则获得的切片长度为j - i,容量为n - i。如果截取操作符存在第三个参数k,其是用来限制新切片容量的。

  1. 下面代码下划线处可以填入哪个选项
func main() {
    var s1 []int
    var s2 = []int{}
    if __ == nil {
        fmt.Println("yes nil")
    }else{
        fmt.Println("no nil")
    }
}

答案:s1

解析:nil 切片和 nil 相等,一般用来表示一个不存在的切片;空切片和 nil 不相等,表示一个空的集合。

  1. 两种切片声明
  • var a []int声明nil切片;

  • a := []int{}声明长度和容量都为0的空切片。

  1. 切片 abc 的长度和容量分别是多少?
func main() {
    s := [3]int{1, 2, 3}
    a := s[:0]
    b := s[:2]
    c := s[1:2:cap(s)]
}

答案:abc 的长度和容量分别是 0 32 31 2

解析:假设一个底层数组a的大小是n,截取切片的操作是a[i: j],则获得的切片长度为j - i,容量为n - i。如果截取操作符存在第三个参数k,其是用来限制新切片容量的。

  1. 下面这段代码输出什么
func main() {

    s1 := []int{1, 2, 3}
    s2 := s1[1:]
    s2[1] = 4
    fmt.Println(s1)
    s2 = append(s2, 5, 6, 7)
    fmt.Println(s1)
}

输出:

[1 2 4]
[1 2 4]

解析:

Go 中切片底层的数据结构是数组。当使用 s1[1:] 获得切片 s2,和 s1 共享同一个底层数组,这会导致 s2[1] = 4 语句影响 s1

append 操作会导致底层数组扩容,生成新的数组,因此追加数据后的 s2 不会影响 s1

但是为什么对 s2 赋值后影响的却是 s1 的第三个元素呢?这是因为切片 s2 是从数组的第二个元素开始,s2 索引为 1 的元素对应的是 s1 索引为 2 的元素。

  1. 下面的代码有什么问题
func main() {
    fmt.Println([...]int{1} == [2]int{1})
    fmt.Println([]int{1} == []int{1})
}

解析:go 中不同类型是不能比较的,而数组长度是数组类型的一部分,所以 […]int{1} 和 [2]int{1} 是两种不同的类型,不能比较;切片是不能比较的。

  1. 下面这段代码输出什么
func change(s ...int) {
    s = append(s,3)
}

func main() {
    slice := make([]int,5,5)
    slice[0] = 1
    slice[1] = 2
    change(slice...)
    fmt.Println(slice)
    change(slice[0:2]...)
    fmt.Println(slice)
}

输出:

[1 2 0 0 0]
[1 2 3 0 0]

解析:

Go 提供的语法糖...,可以将 slice 传进可变函数,不会创建新的切片。

第一次调用 change() 时,append() 操作使切片底层数组发生了扩容,原 slice 的底层数组不会改变;

第二次调用 change() 函数时,获得一个新的切片,它的底层数组和原切片底层数组是重合的,不过长度、容量分别是 2、5,所以在 change() 函数中对底层数组的修改会影响到原切片。

  1. 下面这段代码输出什么
var x = []int{2: 2, 3, 0: 1}

func main() {
    fmt.Println(x)
}

输出:[1 0 2 3]

解析:字面量初始化切片时候,可以指定索引,没有指定索引的元素会在前一个索引基础之上加一,所以输出 [1 0 2 3],而不是 [1 3 2]

  1. 下面的这段代码输出是什么
func main() {
    a := [2]int{5, 6}
    b := [3]int{5, 6}
    if a == b {
        fmt.Println("equal")
    } else {
        fmt.Println("not equal")
    }
}

编译出错,Go中的数组是值类型,可以进行比较,同时数组长度也是数组类型的组成部分,并且Go语言是强类型语言,所以上面的a, b不能进行比较,编译出错。

  1. 下面的这段代码输出什么
package main

import "fmt"

func main() {
    s := make([]int, 3, 9)
    fmt.Println(len(s)) 
    s2 := s[4:8]
    fmt.Println(len(s2)) 
}

输出:3 4

解析:从一个基础切片派生出的子切片的长度可能大于基础切片的长度。

  1. 下面哪一行代码会 panic
package main

func main() {
  var m map[int]bool // nil
  _ = m[123]
  var p *[5]string // nil
  for range p {
    _ = len(p)
  }
  var s []int // nil
  _ = s[:]
  s, s[0] = []int{1, 2}, 9
}

解析:s, s[0] = []int{1, 2}, 9 行。因为左侧的 s[0] 中的 snil

  1. 下面这段代码输出什么
func main() {
    var k = 1
    var s = []int{1, 2}
    k, s[k] = 0, 3
    fmt.Println(s[0] + s[1])
}

输出:4

解析:多重赋值按照以下的两个步骤进行:计算等号左边的索引表达式和取址表达式,接着计算等号右边的表达式;赋值。

Metadata

Metadata

Assignees

No one assigned

    Labels

    GoGolang

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions