Summarize some of the most important knowledge of the language go point (2)

Then yesterday, said today mainly concurrent security, lock and two simple web example

1. concurrent security and lock

Since it comes to security, it would be unsafe to talk about why. Yesterday said goroutine concurrency, so if multiple goroutine access when there is no synchronization with each other at the same time a resource and performs i / o operations, and that this time we called them at a competitive state, is referred to as a race. Let's look at the example of a race

package main

import (
	"fmt"
	"runtime"
	"sync"
)

var (
	count int //定义一个全局变量,之后会对它进行操作
	wg1   sync.WaitGroup
)

func incCounter(id int) {
	defer wg1.Done()
	for i := 0; i < 2; i++ {
		value := count
		runtime.Gosched()
		value++
		count = value
	}

}

func main() {
	wg1.Add(2)
	go incCounter(1)
	go incCounter(2)

	wg1.Wait()
	fmt.Println("最后的count值为:", count)
}

Here Insert Picture Description
Analyze, obviously with the two goroutine, and each goroutine will be performed twice, the results should not be 4 right? Why is 2. This time it comes to race, that is, each goroutine will cover the operation of other goroutine, so there have been errors. This time the importance of the lock is manifested, of course, we can also use atomic function to eliminate the influence of race, but it only supports a few built-in primitive data types, so the lock is the most critical. The most commonly used is the mutex (mutex), it can guarantee the same time only a goroutine can access the resource, and then mutex to modify the code above to see the effect.

package main

import (
	"fmt"
	"runtime"
	"sync"
)

var (
	count int //定义一个全局变量,之后会对它进行操作
	wg1   sync.WaitGroup
	mutex sync.Mutex
)

func incCounter(id int) {
	defer wg1.Done()
	for i := 0; i < 2; i++ {
		mutex.Lock()
		value := count
		runtime.Gosched()
		value++
		count = value
		mutex.Unlock()
	}

}

func main() {
	wg1.Add(2)
	go incCounter(1)
	go incCounter(2)

	wg1.Wait()
	fmt.Println("最后的count值为:", count)
}

Plus the result of a mutex
Here Insert Picture Description
so normal, so mutex can be a good race to prevent the problem.
When a read operation is much greater than the write operation, with a simple mutex is not very wasteful, this time there is a read-write mutex

package main

import (
	"fmt"
	"sync"
	"time"
)

//读写互斥锁:读的次数远远大于写的次数
var (
	x1     int64
	wg1    sync.WaitGroup
	lock1  sync.Mutex   //互斥锁
	rwlock sync.RWMutex //读写互斥锁
)

func read() {
	//lock1.Lock()
	rwlock.RLock()
	time.Sleep(time.Millisecond)
	//lock1.Unlock()
	rwlock.RUnlock()
	wg1.Done()
}

func write() {
	//lock1.Lock()
	rwlock.Lock()
	x1 += 1
	time.Sleep(time.Millisecond * 10)
	//lock1.Unlock()
	rwlock.Unlock()
	wg1.Done()
}

func main() {
	start := time.Now()
	for i := 0; i < 1000; i++ {
		wg1.Add(1)
		go read()
	}

	for i := 0; i < 10; i++ {
		wg1.Add(1)
		go write()
	}
	wg1.Wait()
	fmt.Println(time.Now().Sub(start))
}

//sync.Once  只运行一次
//sync.Map 并发安全的map并且是空接口类型,Store、Load、LoadorStore、Delete、Range

With this example will find the number in the case of reading is far greater than the number of write and read-write mutex speed will be much faster than using a mutex.

Examples of 2.web

The 1.web "HELLO WORLD"

package main

import (
	"fmt"
	"net/http"
)

func handle(write http.ResponseWriter, request *http.Request) {
	fmt.Fprintf(write, "hello world,%s!", request.URL.Path[1:])
}

func main() {
	http.HandleFunc("/", handle)
	http.ListenAndServe(":8081", nil)

Code is very simple, is to set the port to start your web service, then print hello world and the URL information of port
Here Insert Picture Description
2. A simple server and client communications
server

package main

import (
	"bufio"
	"fmt"
	"net"
)

//tcp server demo
func process(conn net.Conn) {
	defer conn.Close()
	for {
		reader := bufio.NewReader(conn)
		var buf [128]byte
		n, err := reader.Read(buf[:])
		if err != nil {
			fmt.Printf("read from conn  failed,err:%v\n", err)
			break
		}
		recv := string(buf[:n])
		fmt.Println("接收到的数据为:", recv)
		conn.Write([]byte("ok"))
	}
}

func main() {
	listen, err := net.Listen("tcp", "127.0.0.1:20000")
	if err != nil {
		fmt.Printf("listen failed,err:%v\n", err)
		return
	}
	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Printf("accept failed,err:%v\n", err)
			continue
		}
		go process(conn)
	}
}

Client

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)

func main() {
	//1.与服务端建立连接
	conn, err := net.Dial("tcp", "127.0.0.1:20000")
	if err != nil {
		fmt.Printf("dial failed,err:%v\n", err)
		return
	}
	//2.利用连接发送接收数据
	input := bufio.NewReader(os.Stdin)
	for {
		s, _ := input.ReadString('\n')
		s = strings.TrimSpace(s)
		if strings.ToUpper(s) == "Q" {
			return
		}
		//给服务端发消息
		_, err := conn.Write([]byte(s))
		if err != nil {
			fmt.Printf("senf failed,err:%v\n", err)
			return
		}

		//从服务器接受回复的消息
		var buf [1024]byte
		n, err := conn.Read(buf[:])
		if err != nil {
			fmt.Printf("read failed,err:%v\n", err)
			return
		}
		fmt.Println("收到服务端回复:", string(buf[:n]))
	}
}

The result:
Here Insert Picture Description
Here Insert Picture Description
in fact mainly use web development framework, like the python flask, django ...... java of ssm, ssh ...... so go out web language, then also use the framework, so recently will go to learn the knowledge of gin .

Published 85 original articles · won praise 55 · views 20000 +

Guess you like

Origin blog.csdn.net/shelgi/article/details/103929345
Recommended