不积跬步,无以至千里

Golang 基本语法学习


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

这其中涉及到两个内容

  1. defer的执行顺序
    在方法a()中,首先对return的结果做赋值,然后执行defer方法,如果有多个defer方法,先执行最后一个defer。 从第二个a()方法可以看到,首先获得返回结果为0,然后依次执行defer方法
  2. 返回的值传递和地址传递 两个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")
}