Go language learning record (3)

1. Go language structure

Define the structure

Structure definitions require the use of type and struct statements. The struct statement defines a new data type with one or more members in the structure. The type statement sets the name of the structure. The format of the structure is as follows:

type struct_variable_type struct {
   member definition
   member definition
   ...
   member definition
}

Once a structure type is defined, it can be used for variable declarations, the syntax is as follows:

variable_name := structure_variable_type {value1, value2...valuen}
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}

Example:

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}


func main() {

    // 创建一个新的结构体
    fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})

    // 也可以使用 key => value 格式
    fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})

    // 忽略的字段为 0 或 空
   fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})

The output is:

{Go language www.runoob.com Go language tutorial 6495407}
{Go language www.runoob.com Go language tutorial 6495407}
{Go language www.runoob.com 0}

The structure definition is also the same as C++ except for the different writing methods. Among them, the structure variable declaration has an additional key->value form. In addition, the content of the structure as a function parameter and the structure pointer is basically the same as that of C++, so it will not be recorded here.

2. Go language slice (Slice)

Go language slices are an abstraction over arrays.

The length of a Go array cannot be changed. Such a collection is not suitable in a specific scenario. Go provides a flexible and powerful built-in type slice ("dynamic array"). Compared with an array, the length of a slice is not fixed. Yes, you can append elements, which may increase the capacity of the slice when appending.

define slice

You can declare an array of unspecified size to define a slice:

var identifier []type

Slices do not need to specify length.

Or use  the make()  function to create slices:

var slice1 []type = make([]type, len)

也可以简写为

slice1 := make([]type, len)

You can also specify the capacity, where  capacity  is an optional parameter.

make([]T, length, capacity)

Here len is the length of the array and also the initial length of the slice.

Here is a review of the definition of an array of variable length:

var variable_name [...] variable_type

A square bracket is "..." and a square bracket is empty, pay attention to the difference between the two.

slice initialization

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

Directly initialize the slice, [] indicates the slice type, {1,2,3}  initialization values ​​are 1,2,3 in turn, and its  cap=len=3 .

s := arr[:] 

Initializes the slice  s , which is a reference to the array arr.

s := arr[startIndex:endIndex] 

Create a new slice from the subscript startIndex to endIndex-1 in arr, that is, intercept an array.

s := arr[startIndex:]     //默认 endIndex 时将表示一直到arr的最后一个元素。

s := arr[:endIndex]       //默认 startIndex 时将表示从 arr 的第一个元素开始。

s1 := s[startIndex:endIndex] //通过切片 s 初始化切片 s1。

s :=make([]int,len,cap)     //通过内置函数 make() 初始化切片s,[]int 标识为其元素类型为 int 的切片。

len() and cap() functions

Slices are indexable, and the length can be obtained by the len() method .

Slices provide the method cap() for calculating capacity, which can measure how long a slice can be .

The following are specific examples:

package main

import "fmt"

func main() {
   var numbers = make([]int,3,5)

   printSlice(numbers)
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)

The output of the above example run is:

len=3 cap=5 slice=[0 0 0]

empty (nil) slice

A slice defaults to nil and has a length of 0 before it is initialized. Examples are as follows:

package main

import "fmt"

func main() {
   var numbers []int

   printSlice(numbers)

   if(numbers == nil){
      fmt.Printf("切片是空的")
   }
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)

The output of the above example run is:

len=0 cap=0 slice=[]
切片是空的

slice interception

You can set the interception slice [lower-bound:upper-bound] by setting the lower limit and upper limit  , examples are as follows:

package main

import "fmt"

func main() {
   /* 创建切片 */
   numbers := []int{0,1,2,3,4,5,6,7,8}  
   printSlice(numbers)

   /* 打印原始切片 */
   fmt.Println("numbers ==", numbers)

   /* 打印子切片从索引1(包含) 到索引4(不包含)*/
   fmt.Println("numbers[1:4] ==", numbers[1:4])

   /* 默认下限为 0*/
   fmt.Println("numbers[:3] ==", numbers[:3])

   /* 默认上限为 len(s)*/
   fmt.Println("numbers[4:] ==", numbers[4:])

   numbers1 := make([]int,0,5)
   printSlice(numbers1)

   /* 打印子切片从索引  0(包含) 到索引 2(不包含) */
   number2 := numbers[:2]
   printSlice(number2)

   /* 打印子切片从索引 2(包含) 到索引 5(不包含) */
   number3 := numbers[2:5]
   printSlice(number3)

}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)

The output of executing the above code is:

len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
len=0 cap=5 slice=[]
len=2 cap=9 slice=[0 1]
len=3 cap=7 slice=[2 3 4]

append() and copy() functions

If we want to increase the capacity of the slice, we must create a new larger slice and copy the content of the original slice.

The code below describes the copy method for copying a slice and the append method for appending new elements to a slice.

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)

   /* 允许追加空切片 */
   numbers = append(numbers, 0)
   printSlice(numbers)

   /* 向切片添加一个元素 */
   numbers = append(numbers, 1)
   printSlice(numbers)

   /* 同时添加多个元素 */
   numbers = append(numbers, 2,3,4)
   printSlice(numbers)

   /* 创建切片 numbers1 是之前切片的两倍容量*/
   numbers1 := make([]int, len(numbers), (cap(numbers))*2)

   /* 拷贝 numbers 的内容到 numbers1 */
   copy(numbers1,numbers)
   printSlice(numbers1)  
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

The output of the above code execution is:

len=0 cap=0 slice=[]
len=1 cap=1 slice=[0]
len=2 cap=2 slice=[0 1]
len=5 cap=6 slice=[0 1 2 3 4]
len=5 cap=12 slice=[0 1 2 3 4]

3. Go language range (Range)

The range keyword in the Go language is used to iterate the elements of an array (array), slice (slice), channel (channel) or collection (map) in a for loop. In arrays and slices it returns the index of the element and the value corresponding to the index, and in collections it returns a key-value pair.

The range format of the for loop can iterate over slices, maps, arrays, strings, etc. The format is as follows:

for key, value := range oldMap {
    newMap[key] = value
}

The key and value in the above code can be omitted.

If you only want to read the key, the format is as follows:

for key := range oldMap
//或者
for key, _ := range oldMap

If you only want to read the value, the format is as follows:

for _, value := range oldMap

Traversing a simple array, the result of 2**%d is the power corresponding to the index:

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
   for i, v := range pow {
      fmt.Printf("2**%d = %d\n", i, v)
   }
}

The output of the above example run is:

2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128

range iterates over other data structures:

package main
import "fmt"
func main() {
    //这是我们使用 range 去求一个 slice 的和。使用数组跟这个很类似
    nums := []int{2, 3, 4}
    sum := 0
    for _, num := range nums {
        sum += num
    }
    fmt.Println("sum:", sum)
    //在数组上使用 range 将传入索引和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。
    for i, num := range nums {
        if num == 3 {
            fmt.Println("index:", i)
        }
    }
    //range 也可以用在 map 的键值对上。
    kvs := map[string]string{"a": "apple", "b": "banana"}
    for k, v := range kvs {
        fmt.Printf("%s -> %s\n", k, v)
    }

    //range也可以用来枚举 Unicode 字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
    for i, c := range "go" {
        fmt.Println(i, c)
    }
}

The output of the above example run is:

sum: 9
index: 1
a -> apple
b -> banana
0 103
1 111

4. Go language Map (collection)

A Map is an unordered collection of key-value pairs. The most important point of Map is to quickly retrieve data through the key, which is similar to an index and points to the value of the data.

Map is a kind of collection, so we can iterate over it like arrays and slices. However, Map is unordered, and we cannot determine the order in which it is returned, because Map is implemented using a hash table.

Define Map

Maps can be defined using the built-in function make or using the map keyword:

/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)

If the map is not initialized, a nil map will be created. A nil map cannot be used to store key-value pairs

The following example demonstrates creating and using a map:

package main

import "fmt"

func main() {
    var countryCapitalMap map[string]string /*创建集合 */
    countryCapitalMap = make(map[string]string)

    /* map插入key - value对,各个国家对应的首都 */
    countryCapitalMap [ "France" ] = "巴黎"
    countryCapitalMap [ "Italy" ] = "罗马"
    countryCapitalMap [ "Japan" ] = "东京"
    countryCapitalMap [ "India " ] = "新德里"

    /*使用键输出地图值 */
    for country := range countryCapitalMap {
        fmt.Println(country, "首都是", countryCapitalMap [country])
    }

    /*查看元素在集合中是否存在 */
    capital, ok := countryCapitalMap [ "American" ] /*如果确定是真实的,则存在,否则不存在 */
    /*fmt.Println(capital) */
    /*fmt.Println(ok) */
    if (ok) {
        fmt.Println("American 的首都是", capital)
    } else {
        fmt.Println("American 的首都不存在")
    }
}

The result of running the above example is:

The capital of France is Paris
The capital of Italy is Rome
The capital of Japan is Tokyo
The capital of India is New Delhi
American capital does not exist

delete() function

The delete() function is used to delete the elements of the collection, and the parameters are map and its corresponding key. Examples are as follows:

package main

import "fmt"

func main() {
        /* 创建map */
        countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}

        fmt.Println("原始地图")

        /* 打印地图 */
        for country := range countryCapitalMap {
                fmt.Println(country, "首都是", countryCapitalMap [ country ])
        }

        /*删除元素*/ delete(countryCapitalMap, "France")
        fmt.Println("法国条目被删除")

        fmt.Println("删除元素后地图")

        /*打印地图*/
        for country := range countryCapitalMap {
                fmt.Println(country, "首都是", countryCapitalMap [ country ])
        }
}

The result of running the above example is:

original map
The capital of India is New delhi
The capital of France is Paris
The capital of Italy is Rome
The capital of Japan is Tokyo
French entry removed
map after removing elements
The capital of Italy is Rome
The capital of Japan is Tokyo
The capital of India is New delhi

The content of the chapter on recursive functions in Go language is exactly the same as that of C++, so it will not be recorded here.

5. Summary

The content of the Go language structure is basically the same as that of C++; the map type is actually basically the same as the map in the STL container of C++, that is, it can be operated more conveniently by using range when traversing the map, and the iterator is used to traverse the map in C++. It will be more cumbersome; slice slince and range are Go-specific content, slince can slice the existing array, or directly replace the function of the array, it is a very convenient function to intercept the array or slice by setting the upper limit and lower limit , the versatility of range to traverse various containers can also make programming easier.

Guess you like

Origin blog.csdn.net/qq_43824745/article/details/126256340