Golang面试题 练习题 - Go语言中文社区

Golang面试题 练习题


整理自golang中文网https://studygolang.com/ 以及公众号 golang来啦

不管面试里用不用得到,万丈高楼平地起,先得从基础做起

package main
 
import (
     "fmt"
)
 
 func main() {
    defer_call()
 }

func defer_call() {
   defer func() { fmt.Println("打印前") }()
   defer func() { fmt.Println("打印中") }()    
   defer func() { fmt.Println("打印后") }()
   panic("触发异常")
}

答案:

打印后
打印中
打印前
触发异常

参考解析:defer 的执行顺序是后进先出。当出现 panic 语句的时候,会先按照 defer 的后进先出的顺序执行,最后才会执行panic。

func main() {
     slice := []int{0,1,2,3}
     m := make(map[int]*int)
     for key,val := range slice {
         m[key] = &val
     }

    for k,v := range m {
        fmt.Println(k,"->",*v)
    }
}

答案:

0 -> 3
0 -> 3
0 -> 3
0 -> 3

参考解析:这是新手常会犯的错误写法,for range 循环的时候会创建每个元素的副本,而不是元素的引用,所以 m[key] = &val 取的都是变量 val 的地址,所以最后 map 中的所有元素的值都是变量 val 的地址,因为最后 val 被赋值为3,所有输出都是3.

3.下面两段代码输出什么

// 1.
func main() {
   s := make([]int, 5)
   s = append(s, 1, 2, 3)
   fmt.Println(s)
}

// 2.
func main() {
    s := make([]int,0)
    s = append(s,1,2,3,4)
    fmt.Println(s)
}

答案:

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

参考解析:这道题考的是使用 append 向 slice 添加元素,第一段代码常见的错误是 [1 2 3],需要注意
make 分配slice内存元素默认分配0值, slice内存不足底层数组会重新分配

4.下面这段代码有什么缺陷

func funcMui(x,y int)(sum int,error){
    return x+y,nil
}

答案: 返回第二个参数未命名
参考解析:
在函数有多个返回值时,只要有一个返回值有命名,其他的也必须命名。如果有多个返回值必须加上括号();如果只有一个返回值且命名也必须加上括号()。这里的第一个返回值有命名 sum,第二个没有命名,所以错误。

5.new() 与 make() 的区别
参考答案:
new(T) 和 make(T,args) 是 Go 语言内建函数,用来分配内存,但适用的类型不同。

new(T) 会为 T 类型的新值分配已置零的内存空间,并返回地址(指针),即类型为 *T 的值。换句话说就是,返回一个指针,该指针指向新分配的、类型为 T 的零值。适用于值类型,如数组、结构体等。

make(T,args) 返回初始化之后的 T 类型的值,这个值并不是 T 类型的零值,也不是指针 *T,是经过初始化之后的 T 的引用。make() 只适用于 slice、map 和 channel.

6.下面这段代码能否通过编译,不能的话原因是什么;如果能,输出什么

func main() {
    list := new([]int)
    list = append(list, 1)
    fmt.Println(list)
}

参考答案及解析:不能通过编译,new([]int) 之后的 list 是一个 *[]int 类型的指针,不能对指针执行 append 操作。可以使用 make() 初始化之后再用。同样的,map 和 channel 建议使用 make() 或字面量的方式初始化,不要用 new() 。

7.下面这段代码能否通过编译,如果可以,输出什么?

func main() {
    s1 := []int{1, 2, 3}
    s2 := []int{4, 5}
    s1 = append(s1, s2)
    fmt.Println(s1)
}
参考答案及解析:不能通过编译。append() 的第二个参数不能直接使用 slice,需使用 … 操作符,将一个切片追加到另一个切片上:append(s1,s2…)。或者直接跟上元素,形如:append(s1,1,2,3)。

8.下面这段代码能否通过编译,如果可以,输出什么?

var(
    size := 1024
    max_size = size*2
)

func main() {
    fmt.Println(size,max_size)
}
参考答案及解析:不能通过编译。这道题的主要知识点是变量声明的简短模式,形如:x := 100。但这种声明方式有限制:
必须使用显示初始化;
不能提供数据类型,编译器会自动推导;
只能在函数内部使用简短模式;

9.下面这段代码能否通过编译?不能的话,原因是什么?如果通过,输出什么?

  func main() {
     sn1 := struct {
         age  int
         name string
     }{age: 11, name: "qq"}
    sn2 := struct {
         age  int
         name string
     }{age: 11, name: "qq"}

    if sn1 == sn2 {
        fmt.Println("sn1 == sn2")
    }

    sm1 := struct {
        age int
        m   map[string]string
    }{age: 11, m: map[string]string{"a": "1"}}
    sm2 := struct {
        age int
        m   map[string]string
    }{age: 11, m: map[string]string{"a": "1"}}

    if sm1 == sm2 {
        fmt.Println("sm1 == sm2")
    }
 }

参考答案及解析:编译不通过 invalid operation: sm1 == sm2

这道题目考的是结构体的比较,有几个需要注意的地方:

1>. 结构体只能比较是否相等,但是不能比较大小。

2>. 相同类型的结构体才能够进行比较,结构体是否相同不但与属性类型有关,还与属性顺序相关,sn3 与 sn1 就是不同的结构体;

    sn3:= struct {
        name string
        age  int4    }{age:11,name:"qq"}

3>. 如果 struct 的所有成员都可以比较,则该 struct 就可以通过 == 或 != 进行比较是否相等,比较时逐个项进行比较,如果每一项都相等,则两个结构体才相等,否则不相等;

那什么是可比较的呢,常见的有 bool、数值型、字符、指针、数组等,像切片、map、函数等是不能比较的。 具体可以参考 Go 说明文档。http://docs.studygolang.com/ref/spec#Comparison_operators

10.通过指针变量 p 访问其成员变量 name,有哪几种方式?
A.p.name
B.(&p).name
C.(*p).name
D.p->name
参考答案及解析:A C

11.下面这段代码能否通过编译?如果通过,输出什么?

 package main
 
 import "fmt"
 
 type MyInt1 int
 type MyInt2 = int
 
func main() {
    var i int =0
    var i1 MyInt1 = i 
    var i2 MyInt2 = i
    fmt.Println(i1,i2)
}

参考答案及解析:编译不通过,cannot use i (type int) as type MyInt1 in assignment。

这道题考的是类型别名与类型定义的区别。

第 5 行代码是基于类型 int 创建了新类型 MyInt1,第 6 行代码是创建了 int 的类型别名 MyInt2,注意类型别名的定义时 = 。所以,第 10 行代码相当于是将 int 类型的变量赋值给 MyInt1 类型的变量,Go 是强类型语言,编译当然不通过;而 MyInt2 只是 int 的别名,本质上还是 int,可以赋值。

第 10 行代码的赋值可以使用强制类型转化 var i1 MyInt1 = MyInt1(i).

12.关于字符串连接,下面语法正确的是?

A. str := 'abc' + '123'
B. str := "abc" + "123"
C. str := '123' + "abc"
D. fmt.Sprintf("abc%d", 123)

参考答案:B D

知识点:字符串连接。除了以上两种连接方式,还有 strings.Join()、buffer.WriteString()等

13.下面这段代码能否编译通过?如果可以,输出什么?

package main

import "fmt"

const (
    x = iota
    _
    y
    z = "zz"
    k
    p = iota
)

func main()  {
    fmt.Println(x,y,z,k,p)
}

参考答案及解析:编译通过,输出:0 2 zz zz 5。知识点:iota 的使用。给大家贴篇文章,讲的很详细
https://www.cnblogs.com/zsy/p/5370052.html

14.下面赋值正确的是()

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

B D

参考答案及解析:BD。知识点:nil 值。nil 只能赋值给指针、chan、func、interface、map 或 slice 类型的变量。强调下 D 选项的 error 类型,它是一种内置接口类型,看下方贴出的源码就知道,所以 D 是对的。

type error interface {
    Error() string
}

15.关于init函数,下面说法正确的是()

A. 一个包中,可以包含多个 init 函数;
B. 程序编译时,先执行依赖包的 init 函数,再执行 main 包内的 init 函数;
C. main 包中,不能有 init 函数;
D. init 函数可以被其他函数调用;
参考答案及解析:AB
关于 init() 函数有几个需要注意的地方:

1> init() 函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等;
2>一个包可以出线多个 init() 函数,一个源文件也可以包含多个 init() 函数;
3> 同一个包中多个 init() 函数的执行顺序没有明确定义,但是不同包的init函数是根据包导入的依赖关系决定的(看下图);


image.png

init() 函数在代码中不能被显示调用、不能被引用(赋值给函数变量),否则出现编译错误;
一个包被引用多次,如 A import B,C import B,A import C,B 被引用多次,但 B 包只会初始化一次;
引入包,不可出现死循坏。即 A import B,B import A,这种情况编译失败;

16.下面这段代码输出什么以及原因?

 func hello() []string {  
     return nil
 }
 
 func main() {  
     h := hello
     if h == nil {
         fmt.Println("nil")
     } else {
        fmt.Println("not nil")
     }
}

A. nil
B. not nil
C. compilation error

答案及解析:B。这道题目里面,是将 hello() 赋值给变量 h,而不是函数的返回值,所以输出 not nil。

17.下面这段代码能否编译通过?如果可以,输出什么?

func GetValue() int {
     return 1
 }
 
 func main() {
     i := GetValue()
     switch i.(type) {
     case int:
       println("int")
     case string:
        println("string")
    case interface{}:
        println("interface")
    default:
        println("unknown")
    }
}

参考答案及解析:编译失败。考点:类型选择,类型选择的语法形如:i.(type),其中 i 是接口,type 是固定关键字,需要注意的是,只有接口类型才可以使用类型选择。看下关于接口的文章。

18.关于channel,下面语法正确的是()

A. var ch chan int
B. ch := make(chan int)
C. <- ch
D. ch <-

参考答案及解析:ABC。A、B都是声明 channel;C 读取 channel;写 channel 是必须带上值,所以 D 错误。

19.下面这段代码输出什么?
A.0
B.1
C.Compilation error

type person struct {  
    name string
}

func main() {  
    var m map[person]int
    p := person{"mike"}
    fmt.Println(m[p])
}

参考答案及解析:A。打印一个 map 中不存在的值时,返回元素类型的零值。这个例子中,m 的类型是 map[person]int,因为 m 中不存在 p,所以打印 int 类型的零值,即 0。

20.下面这段代码输出什么?

A.18
B.5
C.Compilation error

func hello(num ...int) {  
    num[0] = 18
}

func main() {  
    i := []int{5, 6, 7}
    hello(i...)
    fmt.Println(i[0])
}

参考答案及解析:A 。...语法糖把切片传入只要不发生扩容就会影响到原始切片

21.下面这段代码输出什么?

func main() {  
    a := 5
    b := 8.1
    fmt.Println(a + b)
}

A.13.1
B.13
C.compilation error

参考答案及解析:C。a 的类型是 int,b 的类型是 float,两个不同类型的数值不能相加,编译报错。

22.下面这段代码输出什么?

package main

import (  
    "fmt"
)

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

A.3
B.4
C.compilation error
参考答案及解析:B。
知识点:操作符 [i,j]。基于数组(切片)可以使用操作符 [i,j] 创建新的切片,从索引 i,到索引 j 结束,截取已有数组(切片)的任意部分,返回新的切片,新切片的值包含原数组(切片)的 i 索引的值,但是不包含 j 索引的值。i、j 都是可选的,i 如果省略,默认是 0,j 如果省略,默认是原数组(切片)的长度。i、j 都不能超过这个长度值。

假如底层数组的大小为 k,截取之后获得的切片的长度和容量的计算方法:长度:j-i,容量:k-i

截取操作符还可以有第三个参数,形如 [i,j,k],第三个参数 k 用来限制新切片的容量,但不能超过原数组(切片)的底层数组大小。截取获得的切片的长度和容量分别是:j-i、k-i。

所以例子中,切片 t 为 [4],长度和容量都是 1。

详细的知识点可以看下关于切片的文章

23.下面这段代码输出什么?

func main() {
    a := [2]int{5, 6}
    b := [3]int{5, 6}
    if a == b {
        fmt.Println("equal")
    } else {
        fmt.Println("not equal")
    }
}

A. compilation error
B. equal
C. not equal
参考答案及解析:A。Go 中的数组是值类型,可比较,另外一方面,数组的长度也是数组类型的组成部分,所以 a 和 b 是不同的类型,是不能比较的,所以编译错误。

24.关于 cap() 函数的适用类型,下面说法正确的是()
A. array
B. slice
C. map
D. channel

A B D
知识点:cap(),cap() 函数不适用 map。

25.下面这段代码输出什么?

func main() {  
    var i interface{}
    if i == nil {
        fmt.Println("nil")
        return
    }
    fmt.Println("not nil")
}

A. nil
B. not nil
C. compilation error

参考答案及解析:A。当且仅当接口的动态值和动态类型都为 nil 时,接口类型值才为 nil。

关于接口详细的介绍可以看下之前的文章

26.下面这段代码输出什么?

func main() {  
    s := make(map[string]int)
    delete(s, "h")
    fmt.Println(s["h"])
}

A. runtime panic
B. 0
C. compilation error
参考答案及解析:B。删除 map 不存在的键值对时,不会报错,相当于没有任何作用;获取不存在的减值对时,返回值类型对应的零值,所以返回 0。

27.下面属于关键字的是()

A.func
B.struct
C.class
D.defer

参考答案及解析:ABD。知识点:Go 语言的关键字。Go 语言有 25 个关键字,看下图:


image.png

28.下面这段代码输出什么?

func main() {  
    i := -5
    j := +5
    fmt.Printf("%+d %+d", i, j)
}

A. -5 +5
B. +5 +5
C. 0 0

参考答案及解析:A。%d表示输出十进制数字,+表示输出数值的符号。这里不表示取反。

29.下面这段代码输出什么?

type People struct{}

func (p *People) ShowA() {
    fmt.Println("showA")
    p.ShowB()
}
func (p *People) ShowB() {
    fmt.Println("showB")
}

type Teacher struct {
    People
}

func (t *Teacher) ShowB() {
    fmt.Println("teacher showB")
}

func main() {
    t := Teacher{}
    t.ShowB()
}

参考答案及解析:teacher showB。知识点:结构体嵌套。在嵌套结构体中,People 称为内部类型,Teacher 称为外部类型;通过嵌套,内部类型的属性、方法,可以为外部类型所有,就好像是外部类型自己的一样。此外,外部类型还可以定义自己的属性和方法,甚至可以定义与内部相同的方法,这样内部类型的方法就会被“屏蔽”。这个例子中的 ShowB() 就是同名方法。

30.定义一个包内全局字符串变量,下面语法正确的是()
A. var str string
B. str := ""
C. str = ""
D. var str = ""

参考答案及解析:AD。B 只支持局部变量声明;C 是赋值,str 必须在这之前已经声明;

31.下面这段代码输出什么?

type People struct{}

func (p *People) ShowA() {
    fmt.Println("showA")
    p.ShowB()
}
func (p *People) ShowB() {
    fmt.Println("showB")
}

type Teacher struct {
    People
}

func (t *Teacher) ShowB() {
    fmt.Println("teacher showB")
}

func main() {
    t := Teacher{}
    t.ShowA()
}

参考答案及解析:

showA
showB
知识点:结构体嵌套。这道题可以结合第 12 天的第三题一起看,Teacher 没有自己 ShowA(),所以调用内部类型 People 的同名方法,需要注意的是第 5 行代码调用的是 People 自己的 ShowB 方法。

32.下面这段代码输出什么?

func hello(i int) {  
    fmt.Println(i)
}
func main() {  
    i := 5
    defer hello(i)
    i = i + 10
}

参考答案及解析:5。这个例子中,hello() 函数的参数在执行 defer 语句的时候会保存一份副本,在实际调用 hello() 函数时用,所以是 5.

func main() {
    str := "hello"
    str[0] = 'x'
    fmt.Println(str)
}

A. hello
B. xello
C. compilation error

C

34.下面代码输出什么?

func incr(p *int) int {
    *p++
    return *p
}

func main() {
    p :=1
    incr(&p)
    fmt.Println(p)
}

A. 1
B. 2
C. 3

B

35.对 add() 函数调用正确的是()

func add(args ...int) int {

    sum := 0
    for _, arg := range args {
        sum += arg
    }
    return sum
}

A. add(1, 2)
B. add(1, 3, 7)
C. add([]int{1, 2})
D. add([]int{1, 3, 7}…)
A B D

36.下面代码下划线处可以填入哪个选项?

func main() {
    var s1 []int
    var s2 = []int{}
    if __ == nil {
        fmt.Println("yes nil")
    }else{
        fmt.Println("no nil")
    }
}

A. s1
B. s2
C. s1、s2 都可以

C

37.下面这段代码输出什么?

func main() {  
    i := 65
    fmt.Println(string(i))
}

A. A
B. 65
C. compilation error

参考答案及解析:A。UTF-8 编码中,十进制数字 65 对应的符号是 A。

38.下面这段代码输出什么?

type A interface {
    ShowA() int
}

type B interface {
    ShowB() int
}

type Work struct {
    i int
}

func (w Work) ShowA() int {
    return w.i + 10
}

func (w Work) ShowB() int {
    return w.i + 20
}

func main() {
    c := Work{3}
    var a A = c
    var b B = c
    fmt.Println(a.ShowA())
    fmt.Println(b.ShowB())
}

13 23
参考答案及解析:13 23。知识点:接口。一种类型实现多个接口,结构体 Work 分别实现了接口 A、B,所以接口变量 a、b 调用各自的方法 ShowA() 和 ShowB(),输出 13、23。

39.切片 a、b、c 的长度和容量分别是多少?

func main() {
    s := [3]int{1, 2, 3}
    a := s[:0]
    b := s[:2]
    c := s[1:2:cap(s)]
}

参考答案及解析:a、b、c 的长度和容量分别是 0 3、2 3、1 2。知识点:数组或切片的截取操作。截取操作有带 2 个或者 3 个参数,形如:[i:j] 和 [i:j:k],假设截取对象的底层数组长度为 l。在操作符 [i:j] 中,如果 i 省略,默认 0,如果 j 省略,默认底层数组的长度,截取得到的切片长度和容量计算方法是 j-i、l-i。操作符 [i:j:k],k 主要是用来限制切片的容量,但是不能大于数组的长度 l,截取得到的切片长度和容量计算方法是 j-i、k-i

40.下面代码中 A B 两处应该怎么修改才能顺利编译?

func main() {
    var m map[string]int        //A
    m["a"] = 1
    if v := m["b"]; v != nil {  //B
        fmt.Println(v)
    }
}

m := make(map[stringint])
v, ok := m["b"]; ok
在 A 处只声明了map m ,并没有分配内存空间,不能直接赋值,需要使用 make(),都提倡使用 make() 或者字面量的方式直接初始化 map。

B 处,v,k := m["b"] 当 key 为 b 的元素不存在的时候,v 会返回值类型对应的零值,k 返回 false。

  1. 下面代码输出什么?
type A interface {
    ShowA() int
}

type B interface {
    ShowB() int
}

type Work struct {
    i int
}

func (w Work) ShowA() int {
    return w.i + 10
}

func (w Work) ShowB() int {
    return w.i + 20
}

func main() {
    c := Work{3}
    var a A = c
    var b B = c
    fmt.Println(a.ShowB())
    fmt.Println(b.ShowA())
}

A. 23 13
B. compilation error

参考答案及解析:B。知识点:接口的静态类型。a、b 具有相同的动态类型和动态值,分别是结构体 work 和 {3};a 的静态类型是 A,b 的静态类型是 B,接口 A 不包括方法 ShowB(),接口 B 也不包括方法 ShowA(),编译报错。看下编译错误:

a.ShowB undefined (type A has no field or method ShowB)
b.ShowA undefined (type B has no field or method ShowA)

42.下面代码中,x 已声明,y 没有声明,判断每条语句的对错。

 1. x, _ := f()
 2. x, _ = f()
 3. x, y := f()
 4. x, y = f()

参考答案及解析:错、对、对、错。知识点:变量的声明。1.错,x 已经声明,不能使用 :=;2.对;3.对,当多值赋值时,:= 左边的变量无论声明与否都可以;4.错,y 没有声明。

43.下面代码输出什么?

func increaseA() int {
    var i int
    defer func() {
        i++
    }()
    return i
}

func increaseB() (r int) {
    defer func() {
        r++
    }()
    return r
}

func main() {
    fmt.Println(increaseA())
    fmt.Println(increaseB())
}

A. 1 1
B. 0 1
C. 1 0
D. 0 0

B

44.下面代码输出什么?

type A interface {
    ShowA() int
}

type B interface {
    ShowB() int
}

type Work struct {
    i int
}

func (w Work) ShowA() int {
    return w.i + 10
}

func (w Work) ShowB() int {
    return w.i + 20
}

func main() {
    var a A = Work{3}
    s := a.(Work)
    fmt.Println(s.ShowA())
    fmt.Println(s.ShowB())
}

A. 13 23
B. compilation error

A 类型断言可以用来获取接口的底层值, 通常的语法:i.(Type), 其中i是接口,其实i是接口,Type是类型或接口。编译时会自动检测i的动态类型与type是否一致

45.f1()、f2()、f3() 函数分别返回什么?

func f1() (r int) {
    defer func() {
        r++
    }()
    return 0
}

func f2() (r int) {
    t := 5
    defer func() {
        t = t + 5
    }()
    return t
}

func f3() (r int) {
    defer func(r int) {
        r = r + 5
    }(r)
    return 1
}

1 5 1

46.下面的题目输出什么?

type Person struct {
    age int
}

func main() {
    person := &Person{28}

    // 1. 
    defer fmt.Println(person.age)

    // 2.
    defer func(p *Person) {
        fmt.Println(p.age)
    }(person)  

    // 3.
    defer func() {
        fmt.Println(person.age)
    }()

    person.age = 29
}

29 29 28

47.下面代码输出什么?

func f() {
    defer fmt.Println("D")
    fmt.Println("F")
}

func main() {
    f()
    fmt.Println("M")
}

A. F M D
B. D F M
C. F D M

C

48.下面代码输出什么

type Person struct {
    age int
}

func main() {
    person := &Person{28}

    // 1.
    defer fmt.Println(person.age)

    // 2.
    defer func(p *Person) {
        fmt.Println(p.age)
    }(person)

    // 3.
    defer func() {
        fmt.Println(person.age)
    }()

    person = &Person{29}
}

29 28 28

49.下面的两个切片声明中有什么区别?哪个更可取?

A. var a []int
B. a := []int{}

.参考答案及解析:A 声明的是 nil 切片;B 声明的是长度和容量都为 0 的空切片。第一种切片声明不会分配内存,优先选择

50.A、B、C、D 哪些选项有语法错误?

type S struct {
}

func f(x interface{}) {
}

func g(x *interface{}) {
}

func main() {
    s := S{}
    p := &s
    f(s) //A
    g(s) //B
    f(p) //C
    g(p) //D
}

B D

51.下面 A、B 两处应该填入什么代码,才能确保顺利打印出结果?

type S struct {
    m string
}

func f() *S {
    return __  //A
}

func main() {
    p := __    //B
    fmt.Println(p.m) //print "foo"
}

A. &S{"foo"}
B. *f() 或者 f()

f() 函数返回参数是指针类型,所以可以用 & 取结构体的指针;B 处,如果填 *f(),则 p 是 S 类型;如果填 f(),则 p 是 *S 类型,不过都可以使用 p.m 取得结构体的成员

52.下面的代码各有几处语法问题,各是什么?

package main

import (
    "fmt"
)
func main() {
    var x string = nil

    if x == nil {
        x = "default"
    }
    fmt.Println(x)
}

string 不能是nil 不能和nil 比较

53.return 之后的 defer 语句会执行吗,下面这段代码输出什么?

var a bool = true
func main() {
    defer func(){
        fmt.Println("1")
    }()
    if a == true {
        fmt.Println("2")
        return
    }
    defer func(){
        fmt.Println("3")
    }()
}

参考答案及解析:2 1。defer 关键字后面的函数或者方法想要执行必须先注册,return 之后的 defer 是不能注册的, 也就不能执行后面的函数或方法。

54.下面这段代码输出什么?为什么?

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)
}

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

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

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

image

55.下面选项正确的是?

func main() {
    if a := 1; false {
    } else if b := 2; false {
    } else {
        println(a, b)
    }
}

A. 1 2
B. compilation error

A

版权声明:本文来源简书,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.jianshu.com/p/482a218eb253
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-01-29 15:38:59
  • 阅读 ( 1947 )
  • 分类:面试题

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢