每次学习并整理一个Golang的知识点,每天进步一点点。今天学习下init和的知识点🤔。

代码片段

  1. (多选)关于init函数,下面说法正确的是()
  • A. 一个包中,可以包含多个 init 函数;
  • B. 程序编译时,先执行依赖包的 init 函数,再执行 main 包内的 init 函数;
  • C. main 包中,不能有 init 函数;
  • D. init 函数可以被其他函数调用;
  1. 观察下面代码片段,判断能否编译通过?如果可以,写出输出结果?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

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

思考后看答案

思考后看下方答案…


答疑解惑

参考答案:

1. AB 关于init() 函数有几个需要注意的地方:

  • init() 函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等;
  • 一个包可以出现多个 init() 函数,一个源文件也可以包含多个 init() 函数;
  • 同一个包中多个 init() 函数的执行顺序没有明确定义,但是不同包的init函数是根据包导入的依赖关系决定的;
  • init() 函数在代码中不能被显示调用、不能被引用(赋值给函数变量),否则出现编译错误;
  • 一个包被引用多次,如 A import B,C import B,A import C,B 被引用多次,但 B 包只会初始化一次;
  • 引入包,不可出现死循坏。即 A import B,B import A,这种情况编译失败;

同时在Uber的go语言编程规范中,关于init函数给出的建议是:尽快避免使用init()

init()是不可避免或可取的,代码应先尝试:

  • 无论程序环境或调用如何,都要完全确定。
  • 避免依赖于其他init()函数的顺序或副作用。虽然init()顺序是明确的,但代码可以更改, 因此init()函数之间的关系可能会使代码变得脆弱和容易出错。
  • 避免访问或操作全局或环境状态,如机器信息、环境变量、工作目录、程序参数/输入等。
  • 避免I/O,包括文件系统、网络和系统调用。

2. 编译失败 考点:类型选择;类型选择的语法形如:i.(type),其中 i 是接口,type 是固定关键字,需要注意的是,只有接口类型才可以使用类型选择。使用interface{}传递任意类型数据是go语言的惯例用法;

你做对了吗?😊

其他相关答案,欢迎在评论区留言补充!

拓展阅读

不定参数类型

不定参数是指函数传入的参数个数为不定数量。为了做到这点,首先需要将函数定义为接受不定参数类型:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func myPrint(args ...interface{}) {
	for _, arg := range args {
		switch arg.(type) {
		case int:
			fmt.Println(arg, "is int type")
		case string:
			fmt.Println(arg, "is string type")
		default:
			fmt.Println(arg, "is unknown type")
		}
	}
}

func main() {
    v1 := "abcd"
	v2 := 2345
	v3 := 3.14
	myPrint(v1, v2, v3)
}

该程序的执行结果为:

1
2
3
abcd is string type
2345 is int type
3.14 is unknown type

形如…type格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数。它是一个语法糖(syntactic sugar)。这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说,使用语法糖能够增加程序的可读性,从而减少程序出错的机会。

从内部实现机理上来说,类型…type本质上是一个数组切片,也就是[]type,这也是为什么上面的参数args可以用for循环来获得每个传入的参数。

下期提问

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

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

2.下面这段代码的输出结果?

  • A.0
  • B.1
  • C.Compilation error
1
2
3
4
5
6
7
8
9
type person struct {  
    name string
}

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

3.下面这段代码的输出结果?

  • A.18
  • B.5
  • C.Compilation error
1
2
3
4
5
6
7
8
9
func hello(num ...int) {  
    num[0] = 18
}

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

答案及解析将在下期文章中给出,欢迎大家在评论区留言,独乐乐不如众乐乐,交流学习,互相进步。


欢迎转发和评论。更多优质原创文章,欢迎关注微信公众号“IYue爱月”或扫描下方二维码:

xujpxm_qrcode_gh