Channel synchronization

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 }

Results:

working... The done/Finished in 3.1 s]

Channel selection

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)
    }
}

Results:

$ go run  main.go
two

Timeout handling

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")
    }
}

Results:

$ go run  main.go
1
time out 1

Non-blocking channel

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: Println("sent message") default: fmt.println ("no message sent")}}

The results of

$ go run  main.go
no message receive
no message sent

Channel closed

func main() { jobs := make(chan int, 5) done := make(chan bool) go func() { for { j, Ok := <-jobs if ok {fmt.println ("receive all jobs", j)} else {fmt.println ("receive all jobs") done < -true Return}}}() for I := 1; i < 3; I ++ {jobs < -i fmt.Println("send all jobs", I)} close(jobs) fmt.Println("send all jobs") <-done}

The results of

$ go run main.go
send job 1
send job 2
send all jobs
receive job  1
receive job  2
receive all jobs

Traverse channel

func main() {
    queue := make(chan string, 3)

    queue <- "one"
    queue <- "two"

    close(queue)

    for elem := range queue {
        fmt.Println(elem)
    }
}

Results:

$ go run main.go
one
two

The timer

func main() { timer1 := time.NewTimer(time.Second * 2) <-timer1.C fmt.Println("timer 1 expired") timer2 := Println("timer 2 expired") stop2 := timer2.stop () FMT.Println("stop2:", stop2) if stop2 {FMT.Println("timer 2 stoped")}}

Results:

$ go run main.go
timer 1 expired
timer 2 expired
stop2: false

In the example above, timer2.stop() returns false because the countdown to timer2 has stopped, and timer2.stop() has not executed. If you want to see the stop effect, you can rewrite the code:

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")
    }
}

Results:

$ go run main.go
timer 1 expired
stop2: true
timer 2 stoped

You can see that stop2 stops the timer and the program exits directly.

You can also use the after method that comes with time

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")
    }
}

Results:

$ go run main.go
timeout

The timer

The difference between the Ticker and the timer is that the timer sends a signal counting down to a certain point in time, while the Ticker sends a message every time until we manually stop it

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")
}

Results:

$go run main.go Tick at 2021-05-20 08:55:17.817703 +0800 CST M =+1.003478727 Tick at 2021-05-20 08:55:18.819047 +0800 CST M =+2.004844288 Tick at 2021-05-20 08:55:19.814649 +0800 CST M =+3.000467753 Tick at 2021-05-20 08:55:20.81894 +0800 CST M =+4.004780216 Ticker stopped Tick at 2021-05-20 08:55:21.815348 +0800 CST M =+5.001210115

The result is to push the current time as a value to the channel every 1 second, and then we loop through the channel to get the value. You can see from the source code that Ticker.C is a channel of type time.

Source:

type Ticker struct {
    C <-chan Time // The channel on which the ticks are delivered.
    r runtimeTimer
}

Work pool

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) // start 5 processes for w := 1; w <= 5; W++ {go worker(w, jobs, results)} for j := 1; j <= 9; j++ { jobs <- j } close(jobs) for r := 1; r <= 9; r++ { <-results } }

Result is used to inform the main process that the execution is finished. When all the execution is finished, the main process ends and exits the task. If there is no result, the main process may exit before the child process is finished. The results of

worker 3 process id 1
worker 1 process id 2
worker 2 process id 3
worker 1 process id 4
worker 2 process id 6
worker 3 process id 5
worker 2 process id 8
worker 1 process id 9
worker 3 process id 7

The speed limit

Func main() {// limit ticker request to execute every 2 seconds := time.tick (time.second * 2) for I := 1; i <= 5; Println("request", I, time.now ())} // make(chan time.time,) 3) for i := 0; i < 3; I++ {limiter < -time.now ()} // then open another thread, Go func() {for t := range time.tick (time.second * 2) {limiter < -t}}() go func() {for t := range time.tick (time.second * 2) {limiter < -t}}() For I := 1; for I := 1; i <= 5; i++ { <-limiter fmt.Println("request", i, time.Now()) } }

Results:

Request 1 2021-05-20 10:09:01.121992 +0800 CST M =+2.005258478 Request 2 2021-05-20 10:09:03.117609 +0800 CST M =+4.000918022 Request 3 2021-05-20 10:09:05.116884 +0800 CST M =+6.000235109 Request 4 2021-05-20 10:09:07.11969 +0800 CST M =+8.003084206 Request 5 2021-05-20 10:09:09.119841 +0800 CST M =+10.003278026 Request 1 2021-05-20 10:09:09.119978 +0800 CST M =+10.003414895 request 2 2021-05-20 10:09:09.120101 +0800 CST M =+10.003538622 Request 3 2021-05-20 10:09:09.12018 +0800 CST M =+10.003616297 Request 4 2021-05-20 10:12:29.322124 +0800 CST M =+12.005434486 Request 5 2021-05-20 10:12:31.322453 +0800 CST m=+14.005806367

Effect: first 5 times, interval 2s, 6th to 8th times, no interval time, 9-10 times again interval 2s execution.

The mutex

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)}

Results:

$ go run main.go
state: map[0:72 1:25 2:36 3:44 4:38]

When the mutex configuration is removed, the code reports an error because it reads and writes a memory address at the same time.

Go state coroutines

Make (chan *readOp) = write (chan *readOp) = write (chan *readOp) = write (chan *readOp) = write (chan *readOp) = write (chan *readOp = 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 is used to ensure that there is only one read or write operation at a time, which is more complicated than mutex.

The sorting

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);

Sort custom rules

Sort by string length

type ByLength []string

func (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)
}

The results of

$ go run main.go
[kiwi apple orage banana]

Regular expressions

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))
}

Results:

true
true
true
peach
[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]+)ch
a <fruit>
a PEACH

The time stamp

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))
}

Results:

2021-05-21 09:19:47 +0800 CST m=+0.000135175 1621559987 1621559987347155000 2021-05-21 09:19:47 +0800 CST The 2021-05-21 09:19:47. 347155 + 0800 CST

Digital resolution

Parses the string to the corresponding numeric type, and an error is reported when it cannot be parsed.

Func main() {f, _ := strconv.parsefloat ("1.234", 64) FMT.Println(f) I, _ := strconv.parseint ("1234", 0, float ("1.234", 64) FMT. 64) fmt.Println(i) k, _ := strconv.Atoi("135") fmt.Println(k) _, e := strconv.Atoi("wat") fmt.Println(e) }

Results:

Parsing: Atoi: Parsing "wat": invalid syntax

Parsing a URL

func main() { s := "postgres://user:[email protected]: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]) // Obtain the path FMT.Println(u.path) // Obtain the parameter value FMT.Println(u.ragment) FMT.Println(u.rayquery)}

Results:

$ go run main.go
user
pass
host.com:5432
host.com
5432
/path
f
k=v

SHA1 hash

Func main() {s := "sha1 shis string" // Create a sha1 object h := sha1.new () // Process h.rite ([]byte(s)) // Bs := h.sum (nil) fmt.println (s) fmt.printf ("%x\n", bs)} bs := h.sum (nil) fmt.println (s) fmt.printf ("%x\n", bs)}

Results:

sha1 shis string
6bf8cad402882fb0fc2aed041dcc79b8e686cfc6

Scan the filter

Func main() {// Get data from the command line 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) } }

Results:

$ echo "nihaoya" |go run main.go
NIHAOYA

Command line arguments

func main() {
    argsWithProg := os.Args
    argsWithoutProg := os.Args[1:]
    arg := os.Args[3]

    fmt.Println(argsWithProg)
    fmt.Println(argsWithoutProg)
    fmt.Println(arg)
}

Results:

[/var/folders/p0/cv96ln_j6t7d6g_lwfwcqgqc0000gn/T/go-build765472776/b001/exe/main a b c d]
[a b c d]
c

The environment variable

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])
    }
}

Results:

FOO: 1
BAR: 
__INTELLIJ_COMMAND_HISTFILE__
HOME
__CF_USER_TEXT_ENCODING
LOGIN_SHELL
PATH
LC_CTYPE
USER
SSH_AUTH_SOCK
TMPDIR
SHELL
LOGNAME
XPC_SERVICE_NAME
GO111MODULE
GOPATH
XPC_FLAGS
GOROOT

Executing system Commands

Func main() {// run time command dateCmd := exec.Command("date") dateOut, err := datecmd.output () if err! = nil {panic(err)} fmt.Println(string(dateOut)) // Run the ls command lsCmd := exec.Command("bash", "-c", "ls-a-l-h ") lsOut, err := lsCmd.Output() if err ! = nil {panic(err)} fmt.Println(string(lsOut)) // Run grep grepCmd := exec.Command("grep", "Hello ") // Get grepIn, _ := grepcmd.stdinpipe () grepOut, Write([]byte("hello grep\ngoodbye grep")) Grepin.close () // Reads the output grepBytes, _ := ioutil.ReadAll(grepOut) grepCmd.Wait() fmt.Println("> grep hello") fmt.Println(string(grepBytes)) }

Results:

$ go run main.go Fri May 21 11:33:32 CST 2021 total 160 drwxr-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 .env drwxr-xr-x 8 liangkai admin 256B May 19 17:47 .idea drwxr-xr-x 3 liangkai admin 96B Apr 30 08:13 .vscode drwxr-xr-x 4 liangkai admin 128B Apr 30 15:37 Other drwxr-xr-x 4 liangkai admin 128B Dec 21 09:13 PracChan drwxr-xr-x 4 liangkai admin 128B Apr 12 16:54 PracCodeSvn drwxr-xr-x 3 liangkai admin 96B Mar 3 10:59 PracExporter drwxr-xr-x 7 liangkai admin 224B Apr 30 15:37  PracHttp drwxr-xr-x 5 liangkai admin 160B Dec 21 09:10 PracInterface drwxr-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 hello hello grep

The system signal

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")

}

Results:

$ go run main.go
waitting signal


^C
interrupt
exiting