当前位置:网站首页>String type, constant type and container type of go language

String type, constant type and container type of go language

2022-07-07 18:23:00 march of Time

go Data types in :
 Insert picture description here

Character type

Golang There is no specific character type in , If you want to store a single character ( Letter ), In general use byte To preserve .
A string is a sequence of characters connected by a fixed length of characters .Go A string of strings is concatenated by a single byte . That is to say, for the traditional string, it is composed of characters , and Go Different strings , It's made up of bytes .
 Insert picture description here

  1. If we save characters in ASCII Tabular , such as [0-1, a-z,A-Z…] It can be saved directly to byte
  2. If the corresponding code value of the saved character is greater than 255, At this time, we can consider using int Type to save
  3. If we need to output as characters , At this point, we need to format the output , namely fmt.Printf(“%c”, c1)…
    stay Go in , The essence of a character is an integer , When output directly , Is the character corresponding to UTF-8 The code value of the code

String type

  1. A string is a sequence of characters connected by a fixed length of characters .Go A string of strings is concatenated by a single byte .Go Language string byte use UTF-8 Code identification Unicode Text
     Insert picture description here
  2. Once the string is assigned , The string cannot be modified : stay Go The string in is immutable .
     Insert picture description here
  3. Two representations of strings
    (1) Double quotes , Can recognize escape characters
    (2) The quotation marks , Output in the native form of a string , Including line breaks and special characters , It can prevent attacks 、 Output source code and other effects
     Insert picture description here

ASCII String and Unicode character string

·ASCII String length uses len() function .

·Unicode String length uses utf8.RuneCountInString() function . If you want to count by the usual number of characters , You need to use Go In language UTF-8 Provided by the package RuneCountInString() function , Statistics Uncode Number of characters .
1. Go through each one ASCII character Traverse ASCII Character usage for The number of loop traversal , Directly take the subscript of each string to get ASCII character , As the following example shows .

theme := " Sniping  start"

for i := 0; i < len(theme); i++ {
    
    fmt.Printf("ascii: %c %d\n", theme[i], theme[i])
}

The code output is as follows :

ascii: ? 231
ascii: 139
ascii: 153
ascii: ? 229
ascii: 135
ascii: ? 187
ascii: 32
ascii: s 115
ascii: t 116
ascii: a 97
ascii: r 114
ascii: t 116
The Chinese characters obtained in this mode “ horrible ”. Because it's not used Unicode, Chinese characters are displayed as garbled .
2. Press Unicode Character traversal string The same thing :

theme := " Sniping  start"

for _, s := range theme {
    
    fmt.Printf("Unicode: %c %d\n", s, s)
}

The program output is as follows :

Unicode: Sniper 29401
Unicode: blow 20987
Unicode: 32
Unicode: s 115
Unicode: t 116
Unicode: a 97
Unicode: r 114
Unicode: t 116
You can see , This time, Chinese characters can be output normally . summary :

·ASCII String traversal directly uses subscripts .

·Unicode String traversal uses for range.

Getting a certain character of a string getting a certain character of a string is a common operation in development . We generally call a certain character in a string :“ Substring ”, English corresponds to substring. Use... In the following example strings.Index() Function searches for another substring in the string , The code is as follows :

tracer := " Final Destination , A god of death bye bye"
comma := strings.Index(tracer, ",")

pos := strings.Index(tracer[comma:], " A god of death ")
fmt.Println(comma, pos, tracer[comma+pos:])

The program output is as follows : 12 3 A god of death bye bye
The code description is as follows :

· The first 2 Line try at tracer Search for Chinese commas in the string of , The returned location exists comma variable , The type is int, From tracer String start ASCII Code position . strings.Index() Functions are not like other languages , Provide a function to search from a certain offset . However, we can slice the string to realize this logic .

· The first 4 In line ,tracer[comma:] from tracer Of comma Position start to tracer Construct a substring at the end of the string , Return to string.Index() Re index . Got pos Is relative to tracer[comma:] Result . comma The position of the comma is 12, and pos It's relative position , The value is 3. In order to get the position of the second God of death , That is, the string after the comma , You have to let comma add pos The relative deviation of , To calculate the 15 The migration , Then slice tracer[comma+pos:] Calculate the final substring , Get the final result :“ A god of death bye bye”.

summary : There are several common methods of string index .

·strings.Index: Forward search substring .

·strings.LastIndex: Reverse search substring . · The starting position of the search can be made by slicing offset .

Modify string

Go Language string cannot directly modify every character element , It can only be realized by reconstructing a new string and assigning it to the original string variable . Please refer to the following code :

     angel := "Heros never die"
      angleBytes := []byte(angel)
        for i := 5; i <= 10; i++ {
    
          angleBytes[i] = ' '
        }
       fmt.Println(string(angleBytes))

After finishing right []byte After the operation , In the 9 That's ok , Use string() take []byte When converting to a string , Recreated a new string .

summary :

·Go The string of a language is immutable .

· When modifying a string , You can convert a string to []byte Make changes .

·[]byte and string You can cast to and fro by casting .

2.6.5  Connection string

The connection string is so simple , Do you still need to learn ? exactly ,Go Language is like most other languages , Use “+” Connect strings , Very intuitive . But here's the problem , Good things are not perfect , Simple things are not necessarily efficient . Except for the plus connection string ,Go There is something similar to StringBuilder To make efficient string connection , for example :

import (
    "bytes"
    "fmt"
)

func main() {
    
   hammer :=" Give me a hammer "
   stick:=" Die "
   var stringBuilder bytes.Buffer
   stringBuilder.WriteString(hammer)
   stringBuilder.WriteString(stick)
   fmt.Print(stringBuilder.String())
}

bytes.Buffer It can buffer and write various byte arrays into it . A string is also an array of bytes , Use WriteString() Method to write . Will need to connect the string , By calling WriteString() Method , write in stringBuilder in , And then through stringBuilder.String() Method to convert the buffer to a string .

format

Formatting is very common in logic . Use formatting functions , Pay attention to the way of writing : fmt.Sprintf( Format style , parameter list …)
· Format style : String form , Format verbs to % start .

stay Go In language , Named continuation of formatting C Language style :

var progress = 2
var target = 8

//  Two parameter format 
title := fmt.Sprintf(" Collected %d A herb , It also needs to be %d It's a complete mission ", progress, target)

fmt.Println(title)

pi := 3.14159
//  Output in the format of the value itself 
variant := fmt.Sprintf("%v %v %v", " Lunar base ", pi, true)

fmt.Println(variant)

//  Anonymous struct declaration , And give the initial value 
profile := &struct {
    
    Name string
    HP  int
}{
    
    Name: "rat",
    HP:  150,
}
fmt.Printf(" Use '%%+v' %+v\n", profile)
fmt.Printf(" Use '%%#v' %#v\n", profile)

fmt.Printf(" Use '%%T' %T\n", profile)

The code output is as follows : Collected 2 A herb , It also needs to be 8 It's a complete mission
“ Lunar base ” 3.14159 true
Use ’%+v’ &{Name:rat HP:150}
Use ’%#v’ &struct { Name string; HP int }{Name:“rat”, HP:150}
Use ’%T’ *struct { Name string; HP int }C In language , Use %d Represents an integer parameter

Constant

Relative to variables , A constant is a constant value , For example, pi . At compile time , Evaluate a constant expression , The calculation results are used in the running period , The result of the calculation cannot be modified . Constants are very simple to express , Like the following code :

const pi = 3.141592

const e = 2.718281
The declaration of constants is very similar to the declaration of variables , Just put var Instead of const. Multiple variables can be declared together , Allied , Constants can also be declared together , Like the following code :

const (
pi = 3.141592

​ e = 2.718281
)
Constant because it's determined at compile time , So it can be used for array declaration , Like the following code : const size = 4

var arr [size]int

Container type

Variables can meet the requirements of functions and codes to a certain extent . If you write some complex algorithms 、 Structure and logic , You need more complex types to implement . This kind of complex type generally has various forms of functions of storing and processing data , Call them “ Containers ”. In many languages , Containers are provided in the form of standard libraries , You can check the code of these standard libraries at any time , Learn how to create , Delete , Maintain memory . Tips : ·C The language does not provide container encapsulation , Developers need to package according to performance requirements , Or use containers provided by third parties . ·C++ The language container is provided through the standard library , Such as vector Corresponding array ,list Corresponding to double linked list ,map Corresponding mapping, etc . This chapter will be for practical purposes , Introduce arrays in detail 、 section 、 mapping , And the addition of the list 、 Delete 、 How to modify and traverse . This chapter can be used as a tutorial , It can also be used as a dictionary , To facilitate developers' daily query and Application .

1. Array

An array is a continuous area of memory of a fixed length . stay Go In language , Arrays are determined from the time of declaration , You can modify the array members when using , But the array size cannot be changed .
Tips :C Language and Go The concept of array in the language is exactly the same .C The language array is also a fixed length memory area , The size of the array is fixed at the time of declaration .
Declaration array
Arrays are written as follows :
var Array variable name [ Element quantity ]T

 var team[2]string
 team[0]="hammmer"
 team[1]="solider"
  perhaps :
 var team = [3]string{
    "hammer","solider","mum"}

But in general , This process can be left to the compiler , Let the compiler at compile time , Determine the size of the array according to the number of elements .

 var team = [...]string{
    "hammer", "soldier", "mum"}

“…” Means to let the compiler determine the size of the array . In the example above , The compiler will automatically set the number of elements for this array to 3.
Use For Loop traversal :

  for k, v := range team {
    
         fmt.Println(k, v)
   }
   //k It's the index ,v Is element value 

2. section (slice)

—— Dynamically allocate continuous space of size
Go The internal structure of the language slice contains the address 、 Size and capacity . Slicing is generally used to quickly manipulate a set of data . If the data set is compared to cut cake , Slice is what you want “ That one ”. The process of cutting involves where to start ( This is the address of the slice ) And how big ( This is the size of the slice )
By default, the slice points to a contiguous area of memory , It could be an array , It can also be the slice itself . Generating slices from contiguous memory regions is a common operation , The format is as follows :
slice [ Starting position : End position ]
·slice Represents the target slice object .
· The start position corresponds to the index of the target slice object .
· The end position corresponds to the end index of the target slice . Generate slices from an array , The code is as follows :

var a  = [3]int{
    1, 2, 3}

fmt.Println(a, a[1:2])

· The number of elements taken out is : End position - Starting position .
· The extracted element does not contain the index corresponding to the end position , The last element of the slice uses slice[len(slice)] obtain .
· When the default start position , Indicates the position from the beginning to the end of the continuous area .
· When the default end position , Indicates from the starting position to the end of the whole continuous area .
· When both default , Equivalent to the slice itself .
· Both are 0 when , Equivalent to an empty slice , Generally used for slice reduction . · Take slices according to the index position slice Element value , The value range is (0~len(slice)-1), If the limit is exceeded, a runtime error will be reported . When generating slices , The end position can be filled in len(slice) But there is no error .

Generate slices from the specified range
Slice and array are inseparable . If the array is understood as an office building , So slicing is to rent different continuous floors to users . The process of renting needs to select the start floor and end floor , This process will generate slices . The sample code is as follows :

var light[30]int
for i:=0;i<30;i++{
    
	light[i]=i+1;
}
fmt.Print(light[2:5])
fmt.Print(light[:10])

 Insert picture description here
Represents the original slice :

a := []int{
    1, 2, 3}

fmt.Println(a[:])

a It's a possession 3 Slices of elements . take a Slice using a[:] After the operation , The obtained slices are similar to a The slices are consistent
Set the start and end of the slice 0 when , The resulting slice will become empty , The code is as follows :

 a := []int{
    1, 2, 3}

fmt.Println(a[0:0])

Declaration slice
Each type can have its slice type , Represents a continuous collection of elements of multiple types . Therefore, the slice type can also be declared . The format of slice type declaration is as follows :
var name []T

·name The variable name representing the slice type .
·T Represents the element type corresponding to the slice type .
The following code shows how to use the slice declaration .

   //  Declare string slicing 
        var strList []string
        
        //  Declare integer slices 
       var numList []int
        
        //  Declare an empty slice 
        var numListEmpty = []int{
    }
        
        //  Output 3 A slice 
        fmt.Println(strList, numList, numListEmpty)
        
        //  Output 3 Slice size 
        fmt.Println(len(strList), len(numList), len(numListEmpty))
        
        //  The result of slice decision null 
        fmt.Println(strList == nil)
      fmt.Println(numList == nil)
        fmt.Println(numListEmpty == nil)

Use make() Function construction slice
If you need to create a slice dynamically , have access to make() Built-in functions , The format is as follows :

make( []T, size, cap )

·T: The element type of the slice .
·size: Is how many elements are allocated to this type .
·cap: Number of pre allocated elements , This value does not affect size, Just able to allocate space in advance , Reduce performance problems caused by multiple allocation of space .
Examples are as follows :

 a := make([]int, 2)
b := make([]int, 2, 10)

fmt.Println(a, b)
fmt.Println(len(a), len(b))

[0 0] [0 0]
2 2
a and b Are pre allocated 2 Slices of elements , It's just b The internal storage space of has been allocated 10 individual , But it actually uses 2 Elements . Capacity does not affect the current number of elements , therefore a and b take len All are 2.

Use append() Function to add elements to the slice
Go Built in functions of language append() You can add elements to slices dynamically . Each slice points to a piece of memory space , This space can hold a certain number of elements . When space cannot hold enough elements , The slice will be “ Capacity expansion ”.“ Capacity expansion ” Operations often occur in append() When a function is called .

        var numbers []int
        
        for i := 0; i < 10; i++ {
    
                numbers = append(numbers, i)
                fmt.Printf("len: %d cap: %d pointer: %p\n", len(numbers), cap(numbers), numbers)
        }

append() Function in addition to adding an element , You can also add many elements at one time .

01        var car []string
02                
03        //  add to 1 Elements  
04        car = append(car, "OldDriver")
05                
06        //  Add multiple elements 
07        car = append(car, "Ice", "Sniper", "Monk")
08        
09        //  Add slices 
10        team := []string{
    "Pig", "Flyingcake", "Chicken"}
11        car = append(car, team...)
12

· The first 11 That's ok , stay team Add... To the back “…”, It means that you will team Add entire to car Behind .
Copy slices :

Use Go Language built in copy() function , You can quickly copy the data of one slice into another slice space ,copy() function

copy( destSlice, srcSlice []T) int

·srcSlice Slice data sources .
·destSlice Target for replication . The target slice must be allocated enough space to hold the number of copied elements . The type of source and target is consistent ,copy The return value of indicates the number of elements actually copied .,


	//  Set the number of elements to 1000
	const elementCount = 1000

	//  Pre allocate enough element slices 
	srcData := make([]int, elementCount)

	//  Assign slice to 
	for i := 0; i < elementCount; i++ {
    
		srcData[i] = i
	}

	//  Reference slice data 
	refData := srcData

	//  Pre allocate enough element slices 
	copyData := make([]int, elementCount)
	//  Copy the data into the new slice space 
	copy(copyData, srcData)

	//  Modify the first element of the original data 
	srcData[0] = 999

	//  Print the first element of the reference slice 
	fmt.Println(refData[0])

	//  Print the first and last elements of the copy slice 
	fmt.Println(copyData[0], copyData[elementCount-1])

	//  Copy the original data from 4 To 6( It doesn't contain )
	copy(copyData, srcData[4:6])

	for i := 0; i < 5; i++ {
    
		fmt.Printf("%d ", copyData[i])
	}

 Insert picture description here

3.map

Go The mapping relation container provided by the language is map.map Use a hash table (hash) Realization . Hash table can be simply described as an array ( Be commonly called “ bucket ”), Each element of the array is a list . Get the eigenvalue of each element according to the hash function , Take the eigenvalue as the key of mapping . If the characteristic value is repeated , Indicates that elements collide . The collided elements will be saved in the list of the same characteristic values . The hash table lookup complexity is O(1), Consistent with array . The worst case scenario is O(n),n Is the total number of elements . Hash needs to avoid element collision as much as possible to improve the search efficiency , So we need to be right “ bucket ” super-popular , Every expansion , Elements need to be put back into the bucket , It's more time consuming .

01        scene := make(map[string]int)
02        
03        scene["route"] = 66
04        
05        fmt.Println(scene["route"])
06        
07        v := scene["route2"]
08        fmt.Println(v)

The code output is as follows :
66
0
The code description is as follows : · The first 1 That's ok map Is an internally implemented type , When using , It needs to be used manually make establish . If not created, use map type , Will trigger downtime errors . · The first 3 Row direction map Add mapping relationship . It is written in the same way as using arrays ,key You can use any type except functions . · The first 5 Row lookup map The value in . · The first 7 In line , Try to find a key that doesn't exist , So what will come back is ValueType The default value of . In some cases , You need to know whether a key in the query is in map in , A special writing method can be used to realize , Look at the code below :
v, ok := scene[“route”]
Based on the default key value , Take an extra variable ok, You can tell the key route Does it exist in map in .

Use delete() Built in functions from map Delete a set of key value pairs in ,delete() The format of the function is as follows : delete(map, key )

scene := make(map[string]int)

//  Get ready map data 
scene["route"] = 66
scene["brazil"] = 4
scene["china"] = 960

delete(scene, "brazil")

for k, v := range scene {
    
        fmt.Println(k, v)
}

Can be used in a concurrent environment map——sync.Map Go In language map In the case of concurrency , Read only is thread safe , Simultaneous read and write threads are unsafe . Let's look at reading and writing in the case of concurrency map Problems that can arise when , The code is as follows :

//  Create a int To int Mapping 
m := make(map[int]int)

//  Open a piece of concurrent code 
go func() {
    
        //  Keep right map To write 
        for {
    
                m[1] = 1
        }

}()

//  Open a piece of concurrent code 
go func() {
    

        //  Keep right map To read 
        for {
    
                _ = m[1]
        }

}()

//  Infinite loop , Let concurrent programs execute in the background 
for {
    

}

Run time output prompt : concurrent map Reading and writing . That is to say, two concurrent functions are used to continuously compare map There is a race problem when reading and writing .map This kind of concurrent operation will be checked internally and found in advance . When concurrent reading and writing is needed , The general way is to lock , But the performance is not high .Go Language in 1.9 Version provides a more efficient concurrent security sync.Map.sync.Map and map Different , Not in the original form of language , But in sync Special structure under the package .
sync.Map It has the following characteristics : · No initialization required , A direct statement is enough . ·sync.Map Out of commission map The method of value selection and setting , But use sync.Map Method to call .Store Indicates storage ,Load Said to get ,Delete Said to delete .
· Use Range With a callback function for traversal operation , Return the internal traversal value through the callback function .Range The return value function of the callback function in the parameter is : When you need to continue iterating , return true; When the iteration is terminated , return false.

02        
03        import (
04                  "fmt"
05                  "sync"
06        )
07        
08        func main() {
    
09        
10                var scene sync.Map
11        
12                //  Save the key value pair to sync.Map
13                scene.Store("greece", 97)
14                scene.Store("london", 100)
15                scene.Store("egypt", 200)
16        
17                //  from sync.Map The value is based on the key 
18                fmt.Println(scene.Load("london"))
19        
20                //  Delete the corresponding key value pair according to the key 
21                scene.Delete("london")
22        
23                //  Traverse all of sync.Map Key value pairs in 
24                scene.Range(func(k, v interface{
    }) bool {
    
25        
26                        fmt.Println("iterate:", k, v)
27                        return true
28                })
29        
30        }

· The first 10 That's ok , Statement scene, The type is sync.Map. Be careful ,sync.Map Out of commission make establish . · The first 13~15 That's ok , Save a series of key value pairs to sync.Map in ,sync.Map Put the key and value in interface{} Type to save .

· The first 18 That's ok , Provide a sync.Map Key to scene.Load() Method and return the value corresponding to the key . · The first 21 That's ok ,sync.Map Of Delete You can use the specified key to delete the corresponding key value pair .
· The first 24 That's ok ,Range() Method can traverse sync.Map, Traversal needs to provide an anonymous function , Parameter is k、v, The type is interface{}, Every time Range() When traversing an element , Will call this anonymous function to return the result .
sync.Map No access provided map The method of quantity , The alternative is to traverse the self calculated quantity when getting .sync.Map In order to ensure concurrent security, there are some performance losses , So in the case of non concurrency , Use map Compared with sync.Map There will be better performance .

list

A list is a container for non contiguous storage , It consists of multiple nodes , Nodes record their relationship with each other through some variables . There are many ways to implement lists , Such as single chain list 、 Double linked list, etc . The principle of list can be understood as follows : hypothesis A、B、C All three have phone numbers , If A Give me the number B,B Give me the number C, This process establishes a single linked list structure
list There are two ways to initialize :New And the statement . The initialization effect of the two methods is the same . 1. adopt container/list Bag New Method initialization list

 Variable name  := list.New()

2. Initialize by declaration

  list  var  Variable name  list.List

List and slice and map The difference is , The list has no restrictions on specific element types . therefore , The elements of the list can be of any type . This brings traversal , It will also lead to some problems . Put values of unexpected types into a list , After taking out the value , take interface{} Downtime will occur when converting to the expected type .

Example :

l := list.New()

//  Tail add 
l.PushBack("canon")

//  Add... To the head 
l.PushFront(67)

//  Save the element handle after the tail is added 
element := l.PushBack("fist")

//  stay “fist” Then add ”high”
l.InsertAfter("high", element)

//  stay “fist” Before adding ”noon”
l.InsertBefore("noon", element)

//  Use 
l.Remove(element)
原网站

版权声明
本文为[march of Time]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207071615034634.html