包
标准库中最常用的包有bufio、bytes、flag、fmt、http、io、json、os、sort、sync和time等包。
包声明
package packagename 指定了某一源文件属于一个包。它应该放在每一个源文件的第一行。
默认的包名就是包导入路径名的最后一段,若导入了两个具有同一包名的包时产生冲突,可以为其中一个包定义别名
例如 mrand “math/rand” // 将名称替换为mrand
导入声明
例如import “fmt”
.
当使用了一个工具包,比如 fmt时,那每次使用它的打印函数打印时,都要 包名+方法名,例如 fmt.Println(" “)。对于频繁使用的包,可以在导入时,使用一个 . 则打印再也不用加 fmt 了。
例如import . “fmt”
Println(” ")
初始化
当包被导入时,会执行该包的 init 函数
尽管一个包可能会被导入多次,但是它只会被初始化一次。
init 函数优先于 main 函数执行
若先导入包,而暂不使用它,或者只是为了确保它进行了初始化,而无需使用包中的任何函数或变量,可以使用空白标识符 _。
自定义的包
创建自定义包
例:
在 geometry 文件夹中,创建一个命名为 rectangle 的文件夹。在 rectangle 文件夹中,所有文件都会以 package rectangle 作为开头,因为它们都属于 rectangle 包。在rectangle 文件夹中,再创建一个名为 rectprops.go 的文件,添加代码。
src
geometry
geometry.go
rectangle
rectprops.go
导入自定义包
导入 rectangle 包:import “geometry/rectangle”
反射
反射可以求出变量和值的类型。
反射是由 reflect 包提供支持. 它定义了两个重要的类型:reflect.Type(接口)和reflect.Value(结构体)
reflect 包中还有一个重要的类型:Kind。Type 表示 interface{} 的实际类型,而 Kind 表示该类型的特定类别。
三大定律
反射可以将接口变量转换为反射对象
reflect.TypeOf(i) :获得接口值的类型
reflect.ValueOf(i):获得接口值的值
由于 TypeOf 和 ValueOf 两个函数接收的是 interface{} 空接口类型,而 Go 语言函数都是值传递,因此Go语言会将我们的类型隐式地转换成接口类型。
反射可以将反射对象转换为接口变量
reflect.Value 的结构体会接收一个 Interface 方法,返回了一个 interface{} 类型的变量
i := v.Interface()
将其还原成原本的类型还需要经过一次强制的类型转换
i := v.Interface() .(int)
要修改反射对象,其值必须可设置
不是接收变量指针创建的反射对象,是不具备可写性的,无法对其进行修改。
是否具备可写性,可使用 CanSet() 来获取得知:
v.CanSet()若为false则不具备
要让反射对象具备可写性:
1.创建反射对象时传入变量的指针
2.使用 Elem()函数返回指针指向的数据
首先通过 reflect.ValueOf 获取变量指针,然后通过 Elem 方法获取指针指向的变量并调用 SetInt 方法更新变量的值:
func main() {
i := 1
v := reflect.ValueOf(&i)
v.Elem().SetInt(10)
fmt.Println(i)
}
异常
panic
当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)。
当某些不应该发生的场景发生时,可以直接调用内置的panic函数:panic(" ")
recover
recover会捕获异常,使程序从panic中恢复,并返回panic value。
必须在 defer 函数中才能生效。
在子协程里触发 panic,只能触发自己协程内的 defer,而无法跨协程。