Channel synchronization

func worker(done chan bool) {
	fmt.Println("working...")
	time.Sleep(2 * time.Second)
	fmt.Println("done")

	done <- true
}

func main(a) {
	done := make(chan bool.1)
	go worker(done)
	<-done
}
Copy the code

Results:

working...
done
[Finished in 3.1s]
Copy the code

Channel selection

import (
	"fmt"
	"time"
)

func main(a) {
	ch1 := make(chan string.1)
	ch2 := make(chan string.2)

	go func(a) {
		time.Sleep(time.Second * 2)
		ch1 <- "one"} ()go func(a) {
		time.Sleep(time.Second)
		ch2 <- "two"} ()select {
	case msg1 := <-ch1:
		fmt.Println(msg1)
	case msg2 := <-ch2:
		fmt.Println(msg2)
	}
}

Copy the code

Results:

$ go run  main.go
two
Copy the code

Timeout handling

func main(a) {
	ch1 := make(chan string.1)

	go func(a) {
		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(a) {
		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")}}Copy the code

Results:

$ go run  main.go
1
time out 1
Copy the code

Non-blocking channel

func main(a) {
	message := make(chan string)

	select {
	case msg := <-message:
		fmt.Print("message", msg)
	default:
		fmt.Println("no message receive")
	}

	msg := "1"
	select {
	case message <- msg: This can be done when the message channel defines a buffer
		fmt.Println("sent message")
	default:
		fmt.Println("no message sent")}}Copy the code

The results of

$ go run  main.go
no message receive
no message sent
Copy the code

Channel closed

func main(a) {
	jobs := make(chan int.5)
	done := make(chan bool)

	go func(a) {
		for {
			j, ok := <-jobs
			if ok {
				fmt.Println("receive job ", j)
			} else {
				fmt.Println("receive all jobs")
				done <- true      // Notify the main program that all tasks have been accepted
				return}}} ()for i := 1; i < 3; i++ {
		jobs <- i
		fmt.Println("send job", i)
	}

	close(jobs)
	fmt.Println("send all jobs")

	<-done  // Wait for notification
}
Copy the code

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
Copy the code

Traverse channel

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

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

	close(queue)

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

Results:

$ go run main.go
one
two
Copy the code

The timer

func main(a) {
	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 is already counting down, so there is no need to stop
	fmt.Println("stop2:", stop2)
	if stop2 {
		fmt.Println("timer 2 stoped")}}Copy the code

Results:

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

In the example above, timer2.stop() is not executed because the countdown to timer2 has stopped, and returns false.

func main(a) {
	timer1 := time.NewTimer(time.Second * 2)
	<-timer1.C
	fmt.Println("timer 1 expired")

	timer2 := time.NewTimer(time.Second * 5)
	go func(a) {
		<-timer2.C
		fmt.Println("timer 2 expired")
	}()

	stop2 := timer2.Stop() 
	fmt.Println("stop2:", stop2)
	if stop2 {
		fmt.Println("timer 2 stoped")}}Copy the code

Results:

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

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(a) {
	ch := make(chan string)

	go func(a) {
		time.Sleep(time.Second * 2)

		ch <- "result"} ()select {
	case res := <-ch:
		fmt.Println(res)
	case <-time.After(time.Second * 1):
		fmt.Println("timeout")}}Copy the code

Results:

$ go run main.go
timeout

Copy the code

The timer

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

func main(a) {
	ticker := time.NewTicker(time.Second)

	go func(a) {
		for t := range ticker.C {
			fmt.Println("Tick at ", t)
		}
	}()

	time.Sleep(time.Second * 5)
	ticker.Stop()

	fmt.Println("ticker stopped")}Copy the code

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
Copy the code

The result is that the current time is pushed as a value to the channel every second, and then we loop through the channel to get the value. Ticker.C is a time-type channel.

Source:

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

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(a) {
	jobs := make(chan int.100)
	results := make(chan int.100)

	// Start 5 processes
	for w := 1; w <= 5; w++ {
		go worker(w, jobs, results)
	}

	// Push tasks to channels
	for j := 1; j <= 9; j++ {
		jobs <- j
	}
    
    close(jobs)
    
	for r := 1; r <= 9; r++ {
		<-results
	}
}
Copy the code

The result function notifies the main process that the execution is complete. When all the execution is complete, the main process ends and exits the task. If there is no result result, the main process exits while the child process is still running. 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
Copy the code

The speed limit

func main(a) {

	// Limit the request to be executed every 2 seconds
	ticker := time.Tick(time.Second * 2)
	for i := 1; i <= 5; i++ {
		<-ticker
		fmt.Println("request", i, time.Now())
	}

	// Push three values to burstylimiter first
	limiter := make(chan time.Time, 3)
	for i := 0; i < 3; i++ {
		limiter <- time.Now()
	}

	// Then start another thread pushing a value to burstylimiter every 2 seconds
	go func(a) {
		for t := range time.Tick(time.Second * 2) {
			limiter <- t
		}
	}()

	// The first three times have no speed limit, the last two times every 2 seconds
	for i := 1; i <= 5; i++ {
		<-limiter
		fmt.Println("request", i, time.Now())
	}

}
Copy the code

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

Copy the code

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

The mutex

func main(a) {
	var state = make(map[int]int)
	var mutex = &sync.Mutex{}

	for w := 0; w < 10; w++ {
		go func(a) {
			for {
				key := rand.Intn(5)
				val := rand.Intn(100)
				mutex.Lock()           / / lock
				state[key] = val
				mutex.Unlock()         / / unlock
			}
		}()
	}

	time.Sleep(time.Second)

	fmt.Println("state:", state)

}
Copy the code

Results:

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

When the mutex configuration is removed, the code reports an error because both read and write to the same memory address.

Go state coroutine

func main(a) {

	reads := make(chan *readOp)
	writes := make(chan *writeOp)

    // Select to ensure that only read or write operations can be performed simultaneously
	go func(a) {
		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(a) {
			for true {
				read := &readOp{
					key:  rand.Intn(5),
					resp: make(chan int),
				}
				reads <- read
			}
		}()
	}

	for w := 0; w < 10; w++ {
		go func(a) {
			for {
				write := &writeOp{
					key:  rand.Intn(5),
					val:  rand.Intn(100),
					resp: make(chan bool),
				}

				writes <- write
				<-write.resp
			}
		}()
	}

	time.Sleep(time.Second)
}
Copy the code

The select option ensures that there is only one read or write operation at the same time, which is more complicated than using a mutex.

The sorting

func main(a) {
	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)
    // Determine whether to sort
	s := sort.IntsAreSorted(ints)
	fmt.Println("Sorted:", s)
}
Copy the code

Custom rule sorting

Sort by string length

type ByLength []string

func (b ByLength) Len(a) 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(a) {
	fruits := []string{"apple"."banana"."kiwi"."orage"}
	sort.Sort(ByLength(fruits))
	fmt.Println(fruits)
}
Copy the code

The results of

$ go run main.go
[kiwi apple orage banana]
Copy the code

Regular expression

func main(a) {
	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))
}
Copy the code

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
Copy the code

The time stamp

func main(a) {
	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))
}
Copy the code

Results:

2021- 05- 21 09:19:47.347155 +0800 CST m=+0.000135175
1621559987
1621559987347155000
2021- 05- 21 09:19:47 +0800 CST
2021- 05- 21 09:19:47.347155 +0800 CST
Copy the code

Digital resolution

Parses the string to the corresponding numeric type. An error is reported when parsing fails.

func main(a) {
	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)
}
Copy the code

Results:

1.234
1234
135
strconv.Atoi: parsing "wat": invalid syntax

Copy the code

Resolving URL Addresses

func main(a) {
	s := "postgres://user:[email protected]:5432/path?k=v#f"

	u, err := url.Parse(s)
	iferr ! =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])

	// Get the path
	fmt.Println(u.Path)

	// Get parameter values
	fmt.Println(u.Fragment)
	fmt.Println(u.RawQuery)
}
Copy the code

Results:

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

SHA1 hash

func main(a) {
	s := "sha1 shis string"

	// Create sha1 object
	h := sha1.New()

	// Handle strings
	h.Write([]byte(s))

	Sumk can be used to append extra bytes to an existing string slice, usually not required
	bs := h.Sum(nil)

	fmt.Println(s)
	fmt.Printf("%x\n", bs)
}
Copy the code

Results:

sha1 shis string
6bf8cad402882fb0fc2aed041dcc79b8e686cfc6

Copy the code

Scan the filter

func main(a) {
	// Get data from the command line
	scanner := bufio.NewScanner(os.Stdin)

	for scanner.Scan() {
		ucl := strings.ToUpper(scanner.Text())
		fmt.Println(ucl)
	}

	iferr := scanner.Err(); err ! =nil {
		fmt.Fprintln(os.Stderr, "error", err)
		os.Exit(1)}}Copy the code

Results:

$ echo "nihaoya" |go run main.go
NIHAOYA
Copy the code

Command line arguments

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

	fmt.Println(argsWithProg)
	fmt.Println(argsWithoutProg)
	fmt.Println(arg)
}
Copy the code

Results:

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

The environment variable

func main(a) {
	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])}}Copy the code

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
Copy the code

Executing system commands

func main(a) {
	// Execute the time command
	dateCmd := exec.Command("date")
	dateOut, err := dateCmd.Output()
	iferr ! =nil {
		panic(err)
	}
	fmt.Println(string(dateOut))

	// Run ls
	lsCmd := exec.Command("bash"."-c"."ls -a -l -h")
	lsOut, err := lsCmd.Output()
	iferr ! =nil {
		panic(err)
	}
	fmt.Println(string(lsOut))

	// Run the grep command
	grepCmd := exec.Command("grep"."hello")

	// Get input and output objects
	grepIn, _ := grepCmd.StdinPipe()
	grepOut, _ := grepCmd.StdoutPipe()

	// Start executing
	grepCmd.Start()

	// Enter characters
	grepIn.Write([]byte("hello grep\ngoodbye grep"))
	grepIn.Close()

	// Read the output
	grepBytes, _ := ioutil.ReadAll(grepOut)
	grepCmd.Wait()
	fmt.Println("> grep hello")
	fmt.Println(string(grepBytes))
}
Copy the code

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

Copy the code

The system signal

func main(a) {

	sigs := make(chan os.Signal, 1)
	done := make(chan bool.1)

	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	go func(a) {
		sig := <-sigs
		fmt.Println()
		fmt.Println(sig)
		done <- true
	}()

	fmt.Println("waitting signal")
	<-done
	fmt.Println("exiting")}Copy the code

Results:

$ go run main.go
waitting signal


^C
interrupt
exiting

Copy the code