通道同步
func worker(done chan bool) { fmt.Println("working...") time.Sleep(2 * time.Second) fmt.Println("done") done <- true}func main() { done := make(chan bool, 1) go worker(done) <-done}
后果:
working...done[Finished in 3.1s]
通道抉择
import ( "fmt" "time")func main() { ch1 := make(chan string, 1) ch2 := make(chan string, 2) go func() { time.Sleep(time.Second * 2) ch1 <- "one" }() go func() { time.Sleep(time.Second) ch2 <- "two" }() select { case msg1 := <-ch1: fmt.Println(msg1) case msg2 := <-ch2: fmt.Println(msg2) }}
后果:
$ go run main.gotwo
超时解决
func main() { ch1 := make(chan string, 1) go func() { time.Sleep(time.Second * 1) ch1 <- "1" }() select { case res := <-ch1: fmt.Println(res) case <-time.After(time.Second * 1): fmt.Println("time out 1") } ch2 := make(chan string, 1) go func() { time.Sleep(time.Second * 2) ch2 <- "2" }() select { case res := <-ch1: fmt.Println(res) case <-time.After(time.Second * 1): fmt.Println("time out 2") }}
后果:
$ go run main.go1time out 1
非阻塞通道
func main() { message := make(chan string) select { case msg := <-message: fmt.Print("message", msg) default: fmt.Println("no message receive") } msg := "1" select { case message <- msg: // 当message通道定义一个缓冲区的时候,这里能够执行 fmt.Println("sent message") default: fmt.Println("no message sent") }}
后果
$ go run main.gono message receiveno message sent
通道敞开
func main() { jobs := make(chan int, 5) done := make(chan bool) go func() { for { j, ok := <-jobs if ok { fmt.Println("receive job ", j) } else { fmt.Println("receive all jobs") done <- true // 告诉主程序,曾经承受全副工作 return } } }() for i := 1; i < 3; i++ { jobs <- i fmt.Println("send job", i) } close(jobs) fmt.Println("send all jobs") <-done //期待告诉}
后果
$ go run main.gosend job 1send job 2send all jobsreceive job 1receive job 2receive all jobs
遍历通道
func main() { queue := make(chan string, 3) queue <- "one" queue <- "two" close(queue) for elem := range queue { fmt.Println(elem) }}
后果:
$ go run main.goonetwo
定时器
func main() { timer1 := time.NewTimer(time.Second * 2) <-timer1.C fmt.Println("timer 1 expired") timer2 := time.NewTimer(time.Second * 2) <-timer2.C fmt.Println("timer 2 expired") stop2 := timer2.Stop() // 此时timer2曾经倒计时完结了,所以不须要进行 fmt.Println("stop2:", stop2) if stop2 { fmt.Println("timer 2 stoped") }}
后果:
$ go run main.gotimer 1 expiredtimer 2 expiredstop2: false
下面例子中,因为timer2的倒计时曾经进行,timer2.stop()没有执行,返回为false,如果想看进行成果,能够改写代码:
func main() { timer1 := time.NewTimer(time.Second * 2) <-timer1.C fmt.Println("timer 1 expired") timer2 := time.NewTimer(time.Second * 5) go func() { <-timer2.C fmt.Println("timer 2 expired") }() stop2 := timer2.Stop() fmt.Println("stop2:", stop2) if stop2 { fmt.Println("timer 2 stoped") }}
后果:
$ go run main.gotimer 1 expiredstop2: truetimer 2 stoped
能够看到stop2进行了计时器,程序间接退出了。
也能够应用time自带的after办法实现
func main() { ch := make(chan string) go func() { time.Sleep(time.Second * 2) ch <- "result" }() select { case res := <-ch: fmt.Println(res) case <-time.After(time.Second * 1): fmt.Println("timeout") }}
后果:
$ go run main.gotimeout
计时器
Ticker和timer的区别是,timer倒计时到某一个工夫点发送一个信号,而ticker是每隔多长时间发送一个信息,直到咱们手动stop
func main() { ticker := time.NewTicker(time.Second) go func() { for t := range ticker.C { fmt.Println("Tick at ", t) } }() time.Sleep(time.Second * 5) ticker.Stop() fmt.Println("ticker stopped")}
后果:
$ go run main.goTick at 2021-05-20 08:55:17.817703 +0800 CST m=+1.003478727Tick at 2021-05-20 08:55:18.819047 +0800 CST m=+2.004844288Tick at 2021-05-20 08:55:19.814649 +0800 CST m=+3.000467753Tick at 2021-05-20 08:55:20.81894 +0800 CST m=+4.004780216ticker stoppedTick at 2021-05-20 08:55:21.815348 +0800 CST m=+5.001210115
后果是每隔1秒将以后工夫作为值push到通道,而后咱们循环这个通道获取值。通过源码能够看到Ticker.C是一个time类型的channel。
源码:
type Ticker struct { C <-chan Time // The channel on which the ticks are delivered. r runtimeTimer}
工作池
func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("worker", id, "process job", j) time.Sleep(time.Second * 2) results <- j }}func main() { jobs := make(chan int, 100) results := make(chan int, 100) // 开启5个过程 for w := 1; w <= 5; w++ { go worker(w, jobs, results) } // 向通道push工作 for j := 1; j <= 9; j++ { jobs <- j } close(jobs) for r := 1; r <= 9; r++ { <-results }}
result作用是告知主过程执行完结,当所有的执行完结后,主过程完结退出工作,如果没有result可能会导致子过程还没有完结,主过程就退出了。
后果
worker 3 process id 1worker 1 process id 2worker 2 process id 3worker 1 process id 4worker 2 process id 6worker 3 process id 5worker 2 process id 8worker 1 process id 9worker 3 process id 7
限速
func main() { // 限度每2秒执行一次申请 ticker := time.Tick(time.Second * 2) for i := 1; i <= 5; i++ { <-ticker fmt.Println("request", i, time.Now()) } // 先向burstylimiter push 3个值 limiter := make(chan time.Time, 3) for i := 0; i < 3; i++ { limiter <- time.Now() } // 而后开启另外一个线程,每2秒向burstylimiter push 一个值 go func() { for t := range time.Tick(time.Second * 2) { limiter <- t } }() // 最初实现成果,前三次没有限速,最初两次每2秒执行一次 for i := 1; i <= 5; i++ { <-limiter fmt.Println("request", i, time.Now()) }}
后果:
request 1 2021-05-20 10:09:01.121992 +0800 CST m=+2.005258478request 2 2021-05-20 10:09:03.117609 +0800 CST m=+4.000918022request 3 2021-05-20 10:09:05.116884 +0800 CST m=+6.000235109request 4 2021-05-20 10:09:07.11969 +0800 CST m=+8.003084206request 5 2021-05-20 10:09:09.119841 +0800 CST m=+10.003278026request 1 2021-05-20 10:09:09.119978 +0800 CST m=+10.003414895request 2 2021-05-20 10:09:09.120101 +0800 CST m=+10.003538622request 3 2021-05-20 10:09:09.12018 +0800 CST m=+10.003616297request 4 2021-05-20 10:12:29.322124 +0800 CST m=+12.005434486request 5 2021-05-20 10:12:31.322453 +0800 CST m=+14.005806367
成果:前5次,距离2s,第6-8次,不间隔时间,9-10次再次距离2s执行。
互斥锁
func main() { var state = make(map[int]int) var mutex = &sync.Mutex{} for w := 0; w < 10; w++ { go func() { for { key := rand.Intn(5) val := rand.Intn(100) mutex.Lock() // 加锁 state[key] = val mutex.Unlock() // 解锁 } }() } time.Sleep(time.Second) fmt.Println("state:", state)}
后果:
$ go run main.gostate: map[0:72 1:25 2:36 3:44 4:38]
当去掉互斥锁配置当前,代码报错,因为同时读写一块内存地址。
go状态协程
func main() { reads := make(chan *readOp) writes := make(chan *writeOp) // 通过select抉择来保障同时只能读或写操作 go func() { var state = make(map[int]int) for { select { case read := <-reads: read.resp <- state[read.key] case writes := <-writes: state[writes.key] = writes.val writes.resp <- true } } }() for r := 0; r < 100; r++ { go func() { for true { read := &readOp{ key: rand.Intn(5), resp: make(chan int), } reads <- read } }() } for w := 0; w < 10; w++ { go func() { for { write := &writeOp{ key: rand.Intn(5), val: rand.Intn(100), resp: make(chan bool), } writes <- write <-write.resp } }() } time.Sleep(time.Second)}
这里通过select抉择来保障同时只有一个读或写操作,这样比通过互斥锁简单。
排序
func main() { strs := []string{"c", "a", "b"} sort.Strings(strs) fmt.Println("Strings:", strs) ints := []int{1, 6, 3, 5, 2} sort.Ints(ints) fmt.Println("Ints:", ints) // 判断是否排序 s := sort.IntsAreSorted(ints) fmt.Println("Sorted:", s)}
自定义规定排序
以字符串长度排序
type ByLength []stringfunc (b ByLength) Len() int { return len(b)}func (b ByLength) Swap(i, j int) { b[i], b[j] = b[j], b[i]}func (b ByLength) Less(i, j int) bool { return len(b[i]) < len(b[j])}func main() { fruits := []string{"apple", "banana", "kiwi", "orage"} sort.Sort(ByLength(fruits)) fmt.Println(fruits)}
后果
$ go run main.go[kiwi apple orage banana]
正则表达式
func main() { match, _ := regexp.MatchString("p([a-z]+)ch", "peach") fmt.Println(match) r, _ := regexp.Compile("p([a-z]+)ch") fmt.Println(r.MatchString("peach")) fmt.Println(r.Match([]byte("peach"))) fmt.Println(r.FindString("peach punch")) fmt.Println(r.FindStringIndex("peach punch")) fmt.Println(r.FindStringSubmatch("peach punch")) fmt.Println(r.FindStringSubmatchIndex("peach punch")) fmt.Println(r.FindAllString("peach punch pinch", -1)) fmt.Println(r.FindAllString("peach punch pinch", 2)) fmt.Println(r.FindAllString("peach punch pinch", 1)) fmt.Println(r.FindAllStringSubmatch("peach pinch punch", -1)) fmt.Println(r.FindAllStringSubmatchIndex("peach pinch punch", -1)) r = regexp.MustCompile("p([a-z]+)ch") fmt.Println(r) fmt.Println(r.ReplaceAllString("a peach", "<fruit>")) in := []byte("a peach") out := r.ReplaceAllFunc(in, bytes.ToUpper) fmt.Println(string(out))}
后果:
truetruetruepeach[0 5][peach ea][0 5 1 3][peach punch pinch][peach punch][peach][[peach ea] [pinch in] [punch un]][[0 5 1 3] [6 11 7 9] [12 17 13 15]]p([a-z]+)cha <fruit>a PEACH
工夫戳
func main() { now := time.Now() secs := now.Unix() nanos := now.UnixNano() fmt.Println(now) fmt.Println(secs) fmt.Println(nanos) fmt.Println(time.Unix(secs, 0)) fmt.Println(time.Unix(0, nanos))}
后果:
2021-05-21 09:19:47.347155 +0800 CST m=+0.000135175162155998716215599873471550002021-05-21 09:19:47 +0800 CST2021-05-21 09:19:47.347155 +0800 CST
数字解析
将字符串解析成对应的数字类型,当遇到无奈解析时,会报错。
func main() { f, _ := strconv.ParseFloat("1.234", 64) fmt.Println(f) i, _ := strconv.ParseInt("1234", 0, 64) fmt.Println(i) k, _ := strconv.Atoi("135") fmt.Println(k) _, e := strconv.Atoi("wat") fmt.Println(e)}
后果:
1.2341234135strconv.Atoi: parsing "wat": invalid syntax
解析URL地址
func main() { s := "postgres://user:pass@host.com:5432/path?k=v#f" u, err := url.Parse(s) if err != nil { panic(err) } fmt.Println(u.User.Username()) p, _ := u.User.Password() fmt.Println(p) fmt.Println(u.Host) fmt.Println(strings.Split(u.Host, ":")[0]) fmt.Println(strings.Split(u.Host, ":")[1]) // 获取门路 fmt.Println(u.Path) // 获取参数值 fmt.Println(u.Fragment) fmt.Println(u.RawQuery)}
后果:
$ go run main.gouserpasshost.com:5432host.com5432/pathfk=v
SHA1散列
func main() { s := "sha1 shis string" // 创立一个sha1对象 h := sha1.New() // 对字符串解决 h.Write([]byte(s)) // sumk能够用来对现有字符串切片追加额定字节,个别不须要 bs := h.Sum(nil) fmt.Println(s) fmt.Printf("%x\n", bs)}
后果:
sha1 shis string6bf8cad402882fb0fc2aed041dcc79b8e686cfc6
Scan过滤
func main() { // 从命令行获取数据 scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { ucl := strings.ToUpper(scanner.Text()) fmt.Println(ucl) } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "error", err) os.Exit(1) }}
后果:
$ echo "nihaoya" |go run main.goNIHAOYA
命令行参数
func main() { argsWithProg := os.Args argsWithoutProg := os.Args[1:] arg := os.Args[3] fmt.Println(argsWithProg) fmt.Println(argsWithoutProg) fmt.Println(arg)}
后果:
[/var/folders/p0/cv96ln_j6t7d6g_lwfwcqgqc0000gn/T/go-build765472776/b001/exe/main a b c d][a b c d]c
环境变量
func main() { os.Setenv("FOO", "1") fmt.Println("FOO:", os.Getenv("FOO")) fmt.Println("BAR:", os.Getenv("BAR")) for _, e := range os.Environ() { pair := strings.Split(e, "=") fmt.Println(pair[0]) }}
后果:
FOO: 1BAR: __INTELLIJ_COMMAND_HISTFILE__HOME__CF_USER_TEXT_ENCODINGLOGIN_SHELLPATHLC_CTYPEUSERSSH_AUTH_SOCKTMPDIRSHELLLOGNAMEXPC_SERVICE_NAMEGO111MODULEGOPATHXPC_FLAGSGOROOT
执行系统命令
func main() { // 执行工夫命令 dateCmd := exec.Command("date") dateOut, err := dateCmd.Output() if err != nil { panic(err) } fmt.Println(string(dateOut)) // 执行ls命令 lsCmd := exec.Command("bash", "-c", "ls -a -l -h") lsOut, err := lsCmd.Output() if err != nil { panic(err) } fmt.Println(string(lsOut)) // 执行grep命令 grepCmd := exec.Command("grep", "hello") // 获取输出和输入对象 grepIn, _ := grepCmd.StdinPipe() grepOut, _ := grepCmd.StdoutPipe() // 开始执行 grepCmd.Start() // 输出字符 grepIn.Write([]byte("hello grep\ngoodbye grep")) grepIn.Close() // 读取输入 grepBytes, _ := ioutil.ReadAll(grepOut) grepCmd.Wait() fmt.Println("> grep hello") fmt.Println(string(grepBytes))}
后果:
$ go run main.goFri May 21 11:33:32 CST 2021total 160drwxr-xr-x 17 liangkai admin 544B May 21 11:33 .drwxr-xr-x@ 21 liangkai admin 672B May 17 17:40 ..-rw-r--r--@ 1 liangkai admin 10K May 17 18:48 .DS_Store-rw-r--r-- 1 liangkai admin 67B Dec 21 12:08 .envdrwxr-xr-x 8 liangkai admin 256B May 19 17:47 .ideadrwxr-xr-x 3 liangkai admin 96B Apr 30 08:13 .vscodedrwxr-xr-x 4 liangkai admin 128B Apr 30 15:37 Otherdrwxr-xr-x 4 liangkai admin 128B Dec 21 09:13 PracChandrwxr-xr-x 4 liangkai admin 128B Apr 12 16:54 PracCodeSvndrwxr-xr-x 3 liangkai admin 96B Mar 3 10:59 PracExporterdrwxr-xr-x 7 liangkai admin 224B Apr 30 15:37 PracHttpdrwxr-xr-x 5 liangkai admin 160B Dec 21 09:10 PracInterfacedrwxr-xr-x 6 liangkai admin 192B Apr 30 14:46 base-rw-r--r-- 1 liangkai admin 147B Feb 20 18:44 config.ini-rw-r--r-- 1 liangkai admin 798B Apr 30 15:41 go.mod-rw-r--r-- 1 liangkai admin 52K Apr 30 15:41 go.sum-rw-r--r--@ 1 liangkai admin 725B May 21 11:33 main.go> grep hellohello grep
零碎信号
func main() { sigs := make(chan os.Signal, 1) done := make(chan bool, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) go func() { sig := <-sigs fmt.Println() fmt.Println(sig) done <- true }() fmt.Println("waitting signal") <-done fmt.Println("exiting")}
后果:
$ go run main.gowaitting signal^Cinterruptexiting