cgo
Calling C code in Go:
/*
int sum(int a, int b) {
return a+b;
}
*/
import "C"
func main() {
println(C.sum(1, 1))
}
- cgo is a technology that allows the go language to call C methods
- cgo needs the cooperation of go scheduler and coroutine stack
- cgo is generally used when the go implementation cannot be found
- cgo does not improve performance and is a temporary solution
defer
defer: The statement after defer will be executed before the function exits.
Ideas:
- The coroutine records defer information and is called when the function exits
- Compile the defer code directly into the end of the function
1.1 Allocation on the heap
- Used before 1.12
- allocate a heap
sched.deferpool
- When encountering a defer statement, put the information in
deferpool
- When the function returns,
deferpool
fetch and execute from
deferpool
Documented on thread struct p
:
type p struct {
// ...
deferpool []*_defer // pool of available defer structs (see panic.go)
deferpoolbuf [32]*_defer
// ...
}
1.2 Allocation on the stack
- Appeared after 1.13
- When encountering a defer statement, put the information on the stack
- When the function returns, it is taken from the stack and executed
- Only one defer information can be saved
2.1 Open coding
- Appeared after 1.14
- If the defer statement can be determined at compile time, rewrite the user code directly, and put the defer statement at the end of the function
func main() {
defer fmt.Println("defer1")
defer fmt.Println("defer2")
fmt.Println("main")
}
recover、panic
panic
- panic will throw an error
- Terminate the coroutine running
- Crash the entire Go program
func main() {
go func() {
panic("panic")
fmt.Println("do")
}()
fmt.Println("main")
time.Sleep(1 * time.Second)
/*
main
panic: panic
*/
}
panic + defer
- Panic will execute all registered defers of this coroutine before exiting the coroutine
- Will not execute defer of other coroutines
func main() {
defer fmt.Println("defer1")
go func() {
defer fmt.Println("defer2")
panic("panic1")
fmt.Println("do")
}()
fmt.Println("main")
time.Sleep(1 * time.Second)
/**
main
defer2
panic: panic1
*/
}
panic + defer + recover
Executing recover in defer can save the coroutine
- If recover is involved, defer will use heap allocation
- In case of a panic, the panic will take out the defer statement from the deferpool and execute it
- Calling recover in defer can terminate the panic process
func main() {
defer fmt.Println("defer1")
go func(){
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered. Error: ", r)
}
}()
panic("panic1")
fmt.Println("do")
}()
fmt.Println("main")
time.Sleep(1 * time.Second)
/**
main
Recovered. Error: panic1
defer1
*/
}
reflection reflect
func main() {
s := "moody"
stype := reflect.TypeOf(s)
fmt.Println("TypeOf s:", stype)
svalue := reflect.ValueOf(s)
fmt.Println("ValueOf s:", svalue)
}
reflect object to object
metadata
- Metadata is "data about data"
- Represent the type of an object as a data type
- Represent the value of an object as a data type
func main() {
s := "go"
// 对象的类型
// 把对象的类型表示成一个接口
stype := reflect.TypeOf(s)
fmt.Println("TypeOf s:", stype) // TypeOf s: string
// 对象的值
// 把对象的值表示成一个接口
svalue := reflect.ValueOf(s)
fmt.Println("ValueOf s:", svalue) // ValueOf s: go
s2 := svalue.Interface().(string)
//
fmt.Println("s2:", s2) // s2: go
}
- runtime.eface is the runtime representation of an empty interface
- runtime.emptyinterface is the reflection package's representation of the empty interface
- When the object is converted to a reflection object, the compiler will convert the input parameter to eface in advance
- When reflecting object to object, restore data according to address and type
reflective call method
Call methods through reflection to achieve decoupling of user methods and frameworks
func MyAdd(a, b int) int {
return a + b }
func CallAdd(f func(a int, b int) int) {
v := reflect.ValueOf(f)
if v.Kind() != reflect.Func {
return
}
argv := make([]reflect.Value, 2)
argv[0] = reflect.ValueOf(1)
argv[1] = reflect.ValueOf(1)
result := v.Call(argv)
fmt.Println(result[0].Int())
}
func main() {
CallAdd(MyAdd)
}