This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

XDM, we all know that Golang is inherently a highly concurrent, highly efficient compiled language

However, we all know that no matter how good the tool is, it is useless to use it incorrectly. Let’s give two common paths to experience it

Struct and map?

The time difference between using temporary structs and maps may not be noticeable when the amount of computation is small, but it becomes obvious when the number increases, and the difference becomes more obvious as the number increases

When we get to the point where both keys and values can be fixed, we choose structs much more efficiently than we choose maps

  • We ran a simulation loop 100 million times to see how long it would take to use each data structure
  • Calculate the current time before loop
  • After the loop, calculate the current time
  • Finally, calculate the difference between the two times, where we use milliseconds
func main(a) {
	t1 :=time.Now().UnixNano()/1e6
	for i := 0; i < 100000000; i++ {
		var test struct {
			Name  string
			hobby string
		}
		test.Name = "xiaomotong"
		test.hobby = "program"
	}
	t2 :=time.Now().UnixNano()/1e6
	fmt.Println("t2 - t1 == ", t2-t1)
}
Copy the code

Run the program to view the effect:

# go run main.go
t1 ==  1634377149185
t2 ==  1634377149221
t2 - t1 ==  36
Copy the code

Using struct mode, it takes 36 ms, how do you feel about this time?

Let’s take a look at using Map

func main(a) {
	t1 :=time.Now().UnixNano()/1e6
	fmt.Println("t1 == ", t1)

	for i := 0; i < 100000000; i++ {
		var test = map[string]interface{}{}
		test["name"] = "xiaomotong"
		test["hobby"] = "program"
	}
	t2 :=time.Now().UnixNano()/1e6
	fmt.Println("t2 == ", t2)
	fmt.Println("t2 - t1 == ", t2-t1)
}
Copy the code

Run the program to view the effect:

# go run main.go
t1 ==  1634377365927
t2 ==  1634377373525
t2 - t1 ==  7598
Copy the code

Using struct mode, it takes 7598 ms

Using map and struct to complete the same data processing, the time difference is 212 times, just this, when we usually code, for the above scenario, which data structure do you choose?

Why is the gap so large

In cases where we can determine fields, we use temporary structs that don’t need to dynamically allocate content at run time,

A map, on the other hand, has to check the index, which can be very time-consuming

How to concatenate strings?

Encoding XDM in the work encountered string concatenation, how to achieve it? Our tools are temporarily provided as follows:

  • use+The way of
  • usefmt.Sprintf() The way of
  • usestrings.JoinThe way of
  • usebufferThe way of

Now, maybe we have different answers, but let’s just do it, and see how long it takes them to process the same string concatenation

with+The way of

  • Let’s loop through appending the string 500,000 times to see how long it takes
func main(a) {

	t1 := time.Now().UnixNano() / 1e6
	fmt.Println("t1 == ", t1)

	s := "xiao"
	for i := 0; i < 500000; i++ {
		s += "motong"
	}

	t2 := time.Now().UnixNano() / 1e6
	fmt.Println("t2 == ", t2)
	fmt.Println("t2 - t1 == ", t2-t1)
}
Copy the code

Run the program to view the effect:

# go run main.go
t1 ==  1634378595642
t2 ==  1634378743119
t2 - t1 ==  147477
Copy the code

XDM is surprised at how slow it is, 147477 ms, which is 2 minutes and 27 seconds

The use of + to process strings in The Go language is performance-intensive, as we can see from the data

usefmt.Sprintf() The way of

func main(a) {

	t1 := time.Now().UnixNano() / 1e6
	fmt.Println("t1 == ", t1)

	s := "xiao"
	for i := 0; i < 500000; i++ {
		s = fmt.Sprintf("%s%s",s,"motong")
	}

	t2 := time.Now().UnixNano() / 1e6
	fmt.Println("t2 == ", t2)
	fmt.Println("t2 - t1 == ", t2-t1)
}
Copy the code

Run the program to view the effect:

# go run main.go
t1 ==  1634378977361
t2 ==  1634379240292
t2 - t1 ==  262931
Copy the code

It took 262,931 ms, 4 minutes and 22 seconds. XDM didn’t realize that FMT.Sprintf was slower than +

usestrings.JoinThe way of

func main(a) {

	t1 := time.Now().UnixNano() / 1e6
	fmt.Println("t1 == ", t1)

	s := "xiao"
	for i := 0; i < 500000; i++ {
		s = strings.Join([]string{s,"motong"},"")
	}

	t2 := time.Now().UnixNano() / 1e6
	fmt.Println("t2 == ", t2)
	fmt.Println("t2 - t1 == ", t2-t1)
}
Copy the code

Run the program to view the effect:

# go run main.go
t1 ==  1634379455304
t2 ==  1634379598227
t2 - t1 ==  142923
Copy the code

It took 142,923 ms, with a total of 2 minutes and 22 seconds, similar to using +

usebufferThe way of

Using buffer is probably the best way to do it,

func main(a) {

	t1 := time.Now().UnixNano() / 1e6
	fmt.Println("t1 == ", t1)

	s := bytes.NewBufferString("xiao")
	for i := 0; i < 500000; i++ {
		s.WriteString("motong")
	}

	t2 := time.Now().UnixNano() / 1e6
	fmt.Println("t2 == ", t2)
	fmt.Println("t2 - t1 == ", t2-t1)
}
Copy the code
# go run main.go
t1 ==  1634378506021
t2 ==  1634378506030
t2 - t1 ==  9
Copy the code

From the above data, we see that the same data is spliced together 500,000 times

  • First, use+The way that needs to be147477 ms
  • Second, usefmt.Sprintf() The way that needs to be262931 ms
  • Third, usestrings.JoinThe way that needs to be142923 ms
  • Fourth, usebufferThe way that needs to be9ms

The method of using buffer is 16,386 times more than the first method, 29,214 times more than the second method, and 15,880 times more than the third method

XDM, if you encounter the above scenario, which way would you choose to use? The comments section can discuss together, whether there is a more efficient way

Welcome to like, follow and favorites

Friends, your support and encouragement, I insist on sharing, improve the quality of the power

All right, that’s it for this time

Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.

I am Nezha, welcome to like, see you next time ~