原文 https://goquiz.github.io/

slice

以下代码执行结果

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. s := []int{1, 2, 3}
  7. ss := s[1:]
  8. ss = append(ss, 4)
  9. for _, v := range ss {
  10. v += 10
  11. }
  12. for i := range ss {
  13. ss[i] += 10
  14. }
  15. fmt.Println(s) // [1,2,3]
  16. }

短变量声明

Assuming x is declared and y is not declared, which clauses below are correct?
假设声明了x,未声明y,以下哪些句子是正确的?

  1. // 假设声明了x,未声明y,
  2. x, _ := f() // := 短变量声明,要求至少有一个新变量
  3. x, _ = f()
  4. x, y := f()
  5. x, y = f()
  6. func main() {
  7. var x int
  8. // x, _ := f() // := 要求至少有一个新变量
  9. // x, _ = f()
  10. // x, y := f() // 正常声明与定义, y是新的变量
  11. x, y = f() // y 未定义
  12. fmt.Println(x)
  13. fmt.Println(y)
  14. }

nil

执行以下代码时将显示什么?并解释为什么println(InitType()== nil)无法编译?

  1. type S struct{}
  2. func (s S) F() {}
  3. type IF interface {
  4. F()
  5. }
  6. func InitType() S {
  7. var s S
  8. return s
  9. }
  10. func InitPointer() *S {
  11. var s *S
  12. return s
  13. }
  14. func InitEfaceType() interface{} {
  15. var s S
  16. return s
  17. }
  18. func InitEfacePointer() interface{} {
  19. var s *S
  20. return s
  21. }
  22. func InitIfaceType() IF {
  23. var s S
  24. return s
  25. }
  26. func InitIfacePointer() IF {
  27. var s *S
  28. return s
  29. }
  30. func main() {
  31. println(InitType() == nil) // nil 不能转换为 struct 类型比较
  32. // println(InitPointer() == nil) // true 接口与引用类型(slice、指针、map、chan和函数)指针的零值是 nil
  33. // println(InitEfaceType() == nil) // false
  34. // println(InitEfacePointer() == nil) // false
  35. // println(InitIfaceType() == nil) // false
  36. // println(InitIfacePointer() == nil) //false
  37. }

map

修正以下代码代中

  1. func main() {
  2. // var m map[string]int
  3. // m["a"] = 1
  4. // if v := m["b"]; v != 0 { // v 未找到,默认返回 int零值,无法与nil值比较
  5. // println(v)
  6. // }
  7. m := make(map[string]int)
  8. m["a"] = 1
  9. // if v, ok := m["b"]; ok {
  10. // println(v)
  11. // }
  12. // if v := m["b"]; v == 0 { // v 原始0值, 与零值无法分别
  13. // println(v)
  14. // }
  15. }

pointer

赶写a和b行中的空白,以在咻打印的输出为 foo

  1. type S struct {
  2. m string
  3. }
  4. func f() *S {
  5. return &S{"foo"}
  6. }
  7. func main() {
  8. p := *f()
  9. print(p.m)
  10. }

接口 interface{} pointers

在ABCD中,哪个存在语法问题

  1. type S struct {
  2. }
  3. func f(x interface{}) {}
  4. func g(x *interface{}) {} // 指针接收者
  5. func main() {
  6. s := S{}
  7. p := &s
  8. f(s) //a
  9. g(s) //b
  10. f(p) //c
  11. g(p) //d
  12. /*
  13. λ go run main.go
  14. # command-line-arguments
  15. .\main.go:41:3: cannot use s (type S) as type *interface {} in argument to g:
  16. *interface {} is pointer to interface, not interface
  17. .\main.go:43:3: cannot use p (type *S) as type *interface {} in argument to g:
  18. *interface {} is pointer to interface, not interface
  19. */
  20. /*
  21. go语言圣经 p123
  22. 总结,在合法的方法调用表达式中,只有符合下面三种形式的语句才能成立:
  23. 1. 实参接收者和形参接收者是同一个类型,比如都是 T 或者 *T
  24. 形参、实参接收都类型相同
  25. 2. 实参接收者是 T类型的变量,而形参接收者是 *T类型(编译器会隐式地获取变量的地址)
  26. 形参是*T指针接收者时,实参必须是 T类型的变量
  27. 3. 实参接收者是 *T类型,而形参接收者是 T类型。(编译器会隐式地解引用接收者,获得实际的取值)
  28. 形参是 T类型,实参*T可以编译
  29. /*
  30. }

临时指针 Temporary Pointer

解释为什么下面的打印输出为333, 并修改A行以确保打印出012

  1. const N = 3
  2. func main() {
  3. // m := make(map[int]*int)
  4. // for i := 0; i < N; i++ {
  5. // m[i] = &i
  6. // }
  7. // for _, v := range m {
  8. // print(*v)
  9. // }
  10. // output: 333
  11. m := make(map[int]*int)
  12. for i := 0; i < N; i++ {
  13. v := int(i) // 强制类型转换
  14. m[i] = &v // 取 v的地址
  15. }
  16. fmt.Printf("%v\n", m)
  17. for _, v := range m {
  18. fmt.Println(*v)
  19. }
  20. }

修改下面的代码,退出外部的for循环

  1. func main() {
  2. // for i := 0; i < 3; i++ {
  3. // for j := 0; j < 3; j++ {
  4. // fmt.Println(i, ", ", j, " ")
  5. // break
  6. // }
  7. // }
  8. // fmt.Println()
  9. outer:
  10. for i := 0; i < 3; i++ {
  11. for j := 0; j < 3; j++ {
  12. fmt.Println(i, ", ", j, " ")
  13. break outer
  14. }
  15. }
  16. }

全局变量

要将g声明为全局变量,下面的哪些句子是正确的

  1. var g // 没类型
  2. var g G
  3. var g = G{}
  4. g := G{} // 错, 只能用在func中

延迟函数

修正以下代码中的错误

  1. func main() {
  2. f, err := os.Open("test.txt")
  3. // defer f.Close()
  4. if err != nil {
  5. return
  6. }
  7. defer f.Close()
  8. b, err := ioutil.ReadAll(f)
  9. fmt.Println(string(b))
  10. }

panic堆

以下代码输出什么

  1. func f1() {
  2. defer fmt.Println("f1-begin")
  3. f2()
  4. defer fmt.Println("f1-end")
  5. }
  6. func f2() {
  7. defer fmt.Println("f2-begin")
  8. f3()
  9. defer fmt.Println("f2-end")
  10. }
  11. func f3() {
  12. defer fmt.Println("f3-begin")
  13. panic(0)
  14. defer fmt.Println("f3-end")
  15. }
  16. func main() {
  17. f1()
  18. }
  19. /*
  20. 一个defer语句就是一个变通的函数或者方法调用,
  21. 函数和参数表达式会在语句执行时求值,
  22. 无论正常(return/函数执行完毕),还是不正常(panic), 实际的调用都推迟到包含 defer语句的函数结束后才执行
  23. f3-begin
  24. f2-being
  25. f1-being
  26. panic
  27. */

recover

image.png

如果 defer(recover) 调用时发生宕机,recover可以终止当前的宕机状态,并且返回宕机的值
如果 recover 在其他任何情况下运行,则它没有任何效果且返回nil

执行以下代码时将显示什么?执行以下代码后,退出代码是什么?

  1. func f() {
  2. defer func() {
  3. if r := recover(); r != nil {
  4. log.Printf("recover: %#v", r)
  5. }
  6. }()
  7. panic(1)
  8. panic(2)
  9. }
  10. func main() {
  11. f()
  12. }
  13. /*
  14. D:\projects\gocode\gostudy\demo04 (master -> origin)
  15. λ go run main.go
  16. 2019/10/22 20:45:06 recover: 1
  17. */

type shadowing

  1. type S1 struct {
  2. }
  3. func (s1 S1) f() {
  4. fmt.Println("S1.fn()")
  5. }
  6. func (s1 S1) g() {
  7. fmt.Println("S1.g()")
  8. }
  9. type S2 struct {
  10. S1
  11. }
  12. func (s2 S2) f() {
  13. fmt.Println("S2.fn()")
  14. }
  15. type I interface {
  16. f()
  17. }
  18. func printType(i I) {
  19. fmt.Printf("%T\n", i)
  20. if s1, ok := i.(S1); ok {
  21. s1.f()
  22. s1.g()
  23. }
  24. if s2, ok := i.(S2); ok {
  25. s2.f()
  26. s2.g()
  27. }
  28. }
  29. func main() {
  30. printType(S1{})
  31. printType(S2{})
  32. }
  33. /*
  34. D:\projects\gocode\gostudy\demo04 (master -> origin)
  35. λ go run main.go
  36. main.S1
  37. S1.fn()
  38. S1.g()
  39. main.S2
  40. S2.fn()
  41. S1.g()
  42. */

参考

https://goquiz.github.io/