当前位置:网站首页>Golang learning essay

Golang learning essay

2022-06-13 01:17:00 A simple heart

One .go Program relative path , Executive distinction ;
Files that depend on relative paths , A path error occurred :
go run and go build Dissimilarity , A temporary directory to execute , One can be executed manually in the compiled Directory , Paths are handled in different ways go run, Constantly generate new temporary files . because go run and go build The execution path of the compiled file is different , The level of execution may also be different , Naturally, there are various unreadable problems .
resolvent :
1. Configure public environment variable method .
2. Transfer parameter method .
Two .Go Study redis agreement
Form of agreement :

*< The number of arguments > CR LF
$< Parameters  1  Number of bytes > CR LF
< Parameters  1  The data of > CR LF
......
$< Parameters  N  Number of bytes > CR LF
< Parameters  N  The data of > CR LF

example :

*3
$3
set
$3
$cls
$3
pwd

Actual demonstration of the agreement :

"*3\r\n$3\r\nset\r\n$3\r\ncls\r\n$3\r\npwd\r\n"

The following procedure :

package main

import (
	"fmt"
	"log"
	"net"
	"os"

	"github.com/redis-protoc/protocol"
)

const (
	Address = "127.0.0.1:6379"
	Network = "tcp"
)

func Conn(network, address string) (net.Conn, error) {
    
	conn, err := net.Dial(network, address)
	if err != nil {
    
		return nil, err
	}

	return conn, nil
}

func main() {
    
	//  Read in parameter 
	args := os.Args[1:]
	fmt.Println("args = ", args)
	if len(args) <= 0 {
    
		log.Fatalf("Os.Args <= 0")
	}

	// redis Parameter format of the protocol :
	// *< The number of arguments > CR LF
	// $< Parameters 1  Number of bytes > CR LF
	// < Parameters 1  The data of > CR LF
	// ...
	// $< Parameters  N  Number of bytes > CR LF
	// < Parameters  N  The data of > CR LF
	|---------------------------|
	//  for example :
	// *3
	// $3
	// SET
	// $5
	// mykey
	// $7
	// myvalue
	//  Get request protocol 
	reqCommand := protocol.GetRequest(args)

	//  Connect  Redis  The server 
	redisConn, err := Conn(Network, Address)
	if err != nil {
    
		log.Fatalf("Conn err: %v", err)
	}

	defer redisConn.Close()

	//  Write request content 
	_, err = redisConn.Write(reqCommand)
	if err != nil {
    
		log.Fatalf("Conn Write err: %v", err)
	}

	//  Read reply 
	command := make([]byte, 1024)
	n, err := redisConn.Read(command)
	if err != nil {
    
		log.Fatalf("Conn Read err: %v", err)
	}
	fmt.Println("command = ", string(command))

	//  Deal with replies 
	reply, err := protocol.GetReply(command[:n])
	if err != nil {
    
		log.Fatalf("protocol.GetReply err: %v", err)
	}

	//  The reply content after processing 
	log.Printf("Reply: %v", reply)
	//  The original reply 
	log.Printf("Command: %v", string(command[:n]))
}

Send Protocol , The successful execution is as follows :

[[email protected]] # go run redis_protoc.go set name cler
args =  [set name cler]
command =  +OK
2021/07/25 16:22:09 Reply: OK
2021/07/25 16:22:09 Command: +OK

Command execution failed :

 When command execution fails , return -1
[[email protected]] # go run redis_protoc.go  get nvr 
args =  [get nvr]
command =  $-1
2021/07/25 16:23:57 Reply: <nil>
2021/07/25 16:23:57 Command: $-1

Assembly agreement :

func GetRequest(args []string) []byte {
    
	req := []string{
    
		"*" + strconv.Itoa(len(args)),
	}

	for _, arg := range args {
    
		req = append(req, "$"+strconv.Itoa(len(arg)))
		req = append(req, arg)
	}

	str := strings.Join(req, "\r\n")
	return []byte(str + "\r\n")
}

The first character of the status byte stream returned by the service :

const (
	StatusReply    = '+'
	ErrorReply     = '-'
	IntegerReply   = ':'
	BulkReply      = '$'
	MultiBulkReply = '*'
	OkReply   = "OK"
	PongReply = "PONG"
)
=========================
 The first character returned by the byte stream indicates the meaning :
     State the reply (status reply) The first byte of  "+"
     Error response (error reply) The first byte of  "-"
     Integer reply (integer reply) The first byte of  ":"
     Batch reply (bulk reply) The first byte of  "$"
     Multiple batch replies (multi bulk reply) The first byte of  "*"

3、 ... and .Go Memory allocation - Escape analysis
1. Concept definition :
The so-called escape analysis , It is the method to determine the dynamic range of the pointer in the compilation stage of the program , Simply put, where the program can access the pointer , Generally speaking, the compiler decides whether to allocate variables to the heap or stack .
2. characteristic :
a. Is there anywhere else ( Nonlocality ) Cited , As long as it can be quoted , Then the variables are allocated to the heap .
b. Some variables are referenced externally even if they are not used , But it may be because the variable is too large , It will also be allocated to the heap ,y Because the stack is too small , Cannot store .
3. The background of escape analysis
a. If all variables are allocated to the heap , Because of the constant application , Free memory , It will not only affect the performance of the program ( Relative to stack ), Memory fragmentation will also occur , besides , Increased pressure on the garbage collection mechanism , As a result, the performance of the program is not high .
therefore , Need to use an on-demand distribution , On demand options , In specific cases , Only by allocating memory in the appropriate location can we make rational use of memory resources , So as to ensure the feasibility of the system & High availability .
4. Several examples of escape analysis occur :
{
-m: Will print out the optimization strategy of escape analysis , In fact, it can be used at most 4 individual -m, But the amount of information is large , One . General use 1 Just one
-l: Function inlining is disabled , Disable... Here inline Can better observe the escape situation , Reduce interference
}
programme 1- The pointer
a. External reference structure

package main

import "fmt"

type UserInfo struct {
    
	Name string
}
func GetUserInfo() *UserInfo {
    
	return &UserInfo{
    }
}
func main() {
    
	_ = GetUserInfo()
}
[email protected] % go build -gcflags '-m -l' yace.go
# command-line-arguments
./yace.go:8:9: &UserInfo literal escapes to heap

As shown above , Indicates the corresponding UserInfo Externally referenced , So memory is allocated to the heap . It's not hard to imagine , Although in GetUserInfo In the method , Local invariant , If allocated on the stack , When the function returns , Automatically recycled , Then it's over , therefore
Consider that the allocated memory should also be on the heap , After all, it is also externally referenced .
programme 2- Type not determined
a. Local pointers are allocated on the stack

package main
func main() {
    

	str := new(string)
	*str = "zhang"
}
[email protected] goBasicGrammer % go build -gcflags '-m -l' yace.go
# command-line-arguments
./yace.go:12:12: new(string) does not escape

As shown above ,str Although it's a pointer , In fact, variables are allocated to the stack , Not applied to external references .
If you add fmt.Println(*str), There will be changes , The following code :

package main
func main() {
    

	str := new(string)
	*str = "zhang"
	fmt.Println(*str);
}
[email protected] goBasicGrammer % go build -gcflags '-m -l' yace.go
# command-line-arguments
./yace.go:14:12: new(string) does not escape
./yace.go:17:13: ... argument does not escape
./yace.go:17:14: *str escapes to heap

As shown above 17:14, here str To the heap , Why use a fmt This kind of variable allocation transfer will occur ?
reason : func Println(a …interface{}) (n int, err error) The receive parameter is a interface Type of , The program cannot determine the specific type of the variable in the editing phase , Therefore, escape analysis will occur , This allocates variables to the heap .

programme 3- Leakage parameters
a. Parameter passing pointer

package main
type UserInfo struct {
    
	Name string
}
func GetUserInfo(u *UserInfo) *UserInfo {
    
	return u
}
func main() {
    
	_ = GetUserInfo(&UserInfo{
    Name: "erl"})
}
[email protected] goBasicGrammer % go build -gcflags '-m -l' yace.go
# command-line-arguments
./yace.go:7:18: leaking param: u to result ~r1 level=0
./yace.go:11:18: &UserInfo literal does not escape

Above , Memory allocated to the stack , Although the call GetUserInfo, It's a pointer , You've done nothing at all? , The original pointer passed is returned directly , Equivalent to no reference , still main In the scope of , So it is allocated to the stack .

Change my , Pass through non pointer variables

package main

type UserInfo struct {
    
	Name string
}
func GetUserInfo(u UserInfo) *UserInfo {
    
	return &u
}
func main() {
    
	_ = GetUserInfo(UserInfo{
    Name: "erl"})
}
[email protected] goBasicGrammer % go build -gcflags '-m -l' yace.go
# command-line-arguments
./yace.go:7:18: moved to heap: u

Above , Parameter passing becomes , Variable , In fact, it is equivalent to the scheme 1 The structure is the same , Because in main Calling method GetUserInfo, Passed parameters , Method parameters produce a copy , If this parameter is assigned on the stack , So the function returns , This parameter is recycled , External references are over , At this time, escape analysis will be generated , Allocate the structure to the heap .

原网站

版权声明
本文为[A simple heart]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202280554098568.html