flag
flag是一个标准代码包,允许在启动程序时,通过命令行参数传入参数值
var inputStr string
func init() {
flag.StringVar(&inputStr, "name", "value", "usage")
}
func main() {
flag.Parse()
fmt.Println(inputStr)
在命令行中运行:go run main.go -name=tt
,输出为tt
flag的其他接口可以查看其源代码
defer
package main
import (
"fmt"
)
func main() {
fmt.Println("return:", *a())
}
func a() *int {
var temp = 0
var i *int = &temp
defer func() {
(*i)++
fmt.Println("defer2:", *i)
}()
defer func() {
(*i)++
fmt.Println("defer1:", *i)
}()
return i
}
输出结果:
defer1: 1
defer2: 2
return: 2
package main
import (
"fmt"
)
func main() {
fmt.Println("return:", a())
}
func a() int {
var i int
defer func() {
i++
fmt.Println("defer2:", i)
}()
defer func() {
i++
fmt.Println("defer1:", i)
}()
return i
}
输出结果:
defer1: 1
defer2: 2
return: 0
这其中涉及到两个内容
- defer的执行顺序
在方法a()中,首先对return的结果做赋值,然后执行defer方法,如果有多个defer方法,先执行最后一个defer。 从第二个a()方法可以看到,首先获得返回结果为0,然后依次执行defer方法 - 返回的值传递和地址传递 两个a()方法的返回结果不同是因为返回结果是地址,一个是值;在打印的时候,第一个a()方法返回的变量的地址的值已经发生了改变,所以再次读取这个地址的值得时候,会获得最新的值,也就是2.
package main
import (
"fmt"
)
func main() {
fmt.Println("return:", b())
}
func b() (i int) {
defer func() {
i++
fmt.Println("defer2:", i)
}()
defer func() {
i++
fmt.Println("defer1:", i)
}()
return i
}
执行结果:
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
defer1: 1
defer2: 2
return: 2
这里区别于上边第二个代码片段的区别在于,一个是方法内的临时变量,一个是全局变量。可见方法内返回临时变量时做的是值传递。
Gosched和sleep
使用:runtime.Gosched()
挂起当前协程,使得其他协程可以执行。go是非抢占式的,所以只有出让cpu后,其他协程才能得以执行;当另一个线程执行完毕,当前线程会继续执行
使用:time.sleep(1)
sleep会中断当前的协程,经过指定时间后再执行
测试代码如下:
package main
import (
"fmt"
//"time"
"runtime"
)
func do(str string) {
for i := 0; i < 10; i++ {
fmt.Println(str, i)
}
}
func say(str string) {
for i := 0; i < 10; i++ {
runtime.Gosched()
//time.Sleep(1 * time.Second)
fmt.Println(str, i)
}
}
func main() {
go do("a")
say("b")
}