It refers to and holds the location of the data, not including itself. It is a data structure that is difficult to express in words.
Each Go has three reference types defined: ** slice **, ** map **, and ** channel **.
A built-in function that can generate three reference types for slice map channels. Since the pattern differs depending on the type, each understanding is required.
These two built-in functions can be used effectively for three reference types, so I will keep them as prerequisite knowledge.
・ ** len ** You can check the number of elements of each type. ・ ** cap ** You can check the capacity of each type.
A data structure that represents something like a ** variable length array **.
As mentioned above, you can generate a type with the built-in function make.
a := make([]int, 5)
a[0] = 1
fmt.Println(a) //[1 0 0 0 0]
An int type slice with a capacity of 5 is generated, and an arbitrary index value is specified. The generation method and behavior are very similar to the array type, but unlike the array type, it is affected by one process when exchanging calls between functions.
Slices have literals that you can generate without using make.
a := []int{ 0, 1, 2, 3, 4 }
fmt.Println(a) //[0 1 2 3 4]
There is a function called ** simple slice type ** and ** complete slice type ** that takes parameters based on existing slices and creates new slices.
First, the simple slice expression takes a range of parameters related to the index of the slice, extracts a part of the slice represented by that parameter, and creates a new slice.
a := []int{ 0, 1, 2, 3, 4 }
fmt.Println(a[0:4]) //[0 1 2 3]
It is necessary to understand the description method because there are variations depending on the parameters to be taken and so on.
Next, unlike the simple slice type, the complete slice type can take three parameters: ** low **: ** high **: ** max **.
a := []int{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
b := a[2:6:8]
fmt.Println(len(b)) //4
fmt.Println(cap(b)) //6
The capacity of a normal array type or slice is determined as ** number of elements --low value **, but if you take a parameter in the form of a complete slice type, ** max --low value ** There is a difference that the capacity is determined by.
You can also refer to the string in either slice expression. However, for multi-byte characters that cannot be expressed in ASCII, it is necessary to specify the index range in the byte string because [] byte is the unit.
Let's see what functions the built-in functions ** append ** and ** copy ** have. -** append ** This is a function that allows you to add slice elements. -** copy ** A function that allows you to copy slice elements.
append.go
a := make([]int, 0, 0)
fmt.Println(cap(a))
a = append(a, []int{ 1, 2, 3 }...)
fmt.Println(a) //[1, 2, 3]
fmt.Println(cap(a)) //4
a = append(a, []int{ 4, 5, 6 }...)
fmt.Println(a) //[1, 2, 3, 4, 5, 6]
fmt.Println(cap(a)) //8
An element is added to the end of a slice with 0 elements and 0 capacity, and fluctuations in capacity are confirmed. From this program, slices have the property of being automatically expanded when the capacity is exceeded and elements are added. At first glance, it looks like it's doubling, but it's important to note that it's not doubling because it depends on the fighting value and the runtime.
In the above case, since the metadata is taken as the return value of append, the append is reflected and the value can be output with cap, but even if append is performed indirectly to the metadata, it is not reflected. It has a nature.
append.go
func test(a []int) {
a = append(a, 3)
}
func main() {
b := make([]int, 1, 2)
test(b)
fmt.Println(cap(b)) //2
}
copy.go
a := []int{ 1, 2, 3, 4, 5 }
b := []int{ 6, 7, 8 }
fmt.Println(copy(a, b), a) //3 [6 7 8 4 5]
The number of copied elements and the copied elements are output. In this way, the element is overwritten from the beginning of the copy target. Even if the number of elements to be copied exceeds the number of elements to be copied, the number of elements to be copied will be copied.
You can also copy a string type, but you need to consider that it will be copied byte by byte, as described above for slice expressions.
A data structure that represents something like an associative array **.
Maps can also be generated with the built-in function make, following the example.
a := make(map[int]string)
a[1] = "test1"
a[2] = "test2"
fmt.Println(a) //map[1:test1 2:test2]
The int type key value and the string type element type are defined, and the key value and element according to the type are assigned and output. Also, by taking a hint to allocate a memory area in the second argument for the number of elements, it can be usefully used when the map is large.
Maps also have literals to generate without using make.
a := map[int]string{ 1: "test1", 2: "test2" }
fmt.Println(a)
Elements can be written on multiple lines for readability, but due to Go's characteristics, the last value must end with a comma to mean continuation.
You can also generate slices in the map.
a := map[int][]int{
1: []int{1}
2: []int{2}
}
fmt.Println(a) //map[1:[1] 2:[2]]
By the way, since [] int in the element specification can be omitted, I think that there is no particular merit to write [] int.
By assigning a variable like ** a [1] **, you can refer to the corresponding key value element, but in Go, the basic type does not have the state of ** nil **. Therefore, if the initial value of the type is set in the element, it will be processed while retaining it. However, you can work around it by using an idiom that assigns to two variables.
a := map[int]string{ 1: "test1", 2: "test2" }
if a, ok := a[1]; ok {
fmt.Printf("%v, %v\n", a, ok) //test1, true
} else {
fmt.Printf("%v, %v\n", a, ok) //※ , false
In the above program, the second variable evaluates if there is an element corresponding to the key and is assigned as a bool type. Branch processing is performed according to the conditional expression, and it is output. Of course, if the assigned key value does not exist in the map, else will be executed and an empty string and false will be output.
delete A built-in function for removing elements from the map.
a := map[int]string{ 1: "test1", 2: "test2" }
fmt.Println(len(a)) //2
delete(a, 2)
fmt.Println(len(a)) //1
** delete ** The change in the number of elements before and after is compared using len. Before delete, the result is as many as the number of elements in the map, but by using delete, you can see that the number of elements is reduced. Since delete can be deleted by specifying an arbitrary key value, it means that "test2" whose key value is 2 is deleted in the above program.
By the way, although there is practical capacity in the map, cap cannot be used due to its nature.
[Previous article (control syntax)](https://qiita.com/noa-1129/items/819f4a8d81dcdd0c19cd#%E3%82%B4%E3%83%AB%E3%83%BC%E3%83% It is a data structure that is responsible for sending and receiving data between goroutines, summarized in 81% E3% 83% B3).
There is a type of channel in a channel.
var a chan int
As we will see later, you can specify subtypes such as ** receive-only channels ** and ** send-only channels **. If not specified, both transmission and reception are possible.
When generated by make, it will be as follows.
a := make(chan int, 5)
You can specify the amount of space that can temporarily hold data called ** buffer size **.
Use channels to send and receive data.
a := make(chan int, 5)
a <- 1 //Send
a <- 2 //Send
fmt.Println(cap(a)) //5
fmt.Println(len(a)) //2
b := <-a //Receive
fmt.Println(b) // 1
fmt.Println(cap(a)) //5
fmt.Println(len(a)) //1
In the above program, a channel with a buffer size of 5 is generated, and the data in the channel is compared when the channel is transmitted and received. First, looking at the capacity and the number of elements when the values of 1 and 2 are sent to channel a, the capacity is the buffer size, so the value is 5, and since two values are sent, the number of elements is 2. Become. Therefore, we receive one value in the variable b. That way, the capacity doesn't change, but the number of elements is reduced by one. Also, since 1 is output from the variable b, it can be seen that data is being sent and received in the relationship of ** first in, first out **.
Now, let's send and receive data between goroutines.
func test(a <- chan int) {
for {
b, ok := <-a
if ok == false {
break
}
fmt.Println(b) //1
} //2
} //3
//4
func main() {
a := make(chan int)
go test(a)
b := 1
for b < 5 {
a <- b
b++
}
close(a)
}
In the above program, the function test for receiving the channel that takes an arbitrary argument is defined, and when channel a is closed (returns a false value), branch processing that interrupts the loop during output is performed. I am. Then, the function main shares the goroutine that creates the channel a used by the function test and continues to send the variable b that increments until the value is less than 5, and the function test is the value received from the channel. Continues to output. Since it is closed when the data transmission is completed, when the value is 5 or more, the second argument ok returns false and the processing ends.
If there are two or more channels that represent the reception of a variable, the goroutine will stop if the previous channel cannot receive it. The control syntax select can solve this problem.
a := make(chan int, 1)
b := make(chan int, 1)
b <- 5
select {
case <- a:
fmt.Println("x is done")
case <- b:
fmt.Println("y is done") //output
default:
fmt.Println("?")
}
The variable a has a channel generated, but cannot be received because it has not been sent. Normally, the goroutine would stop at this point, but because it uses the select syntax, the process continues. Also, if the processing of multiple cases is successful, it will be executed randomly.
This time I summarized the reference type! !! The reference type has a lot of content, and all the idioms that appear frequently in Go programs, so I want to understand it well.
Author Aiga Matsuo [Shoeisha Starting Go Language](https://www.shoeisha.co.jp/search?search=%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%86% E3% 82% A3% E3% 83% B3% E3% 82% B0Go% E8% A8% 80% E8% AA% 9E)
Recommended Posts