4.3 Strings and derived types in Go

2. String and character types

String:string

var str string
str = "Hello Go"
ch := str[0]  //'H'

//格式化输出
fmt.Printf("The length of \"%s\" is %d \n", str, len(str)) 
fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)
// 转义字符:\

Escape character: \
  • \n: newline character
  • \r: carriage return character
  • \t:tab key
  • \uor \U: Unicode character
  • \\: backslash itself
string is an immutable value type

Although the characters in the string can be accessed through array subscripts, unlike arrays, in the Go language, the string is an immutable value type. Once initialized, its content cannot be modified. For example, look at the following example :

str := "Hello world"
str[0] = 'X' // 编译错误

The compiler reports an error:cannot assign to str[0]

Character Encoding

Strings in the Go language are UTF-8 encoded Unicode character sequences by default, so they can contain non-ANSI characters. For example, "Hello, Academy Master" can appear in Go code. But it should be noted that if your Go code needs to contain non-ANSI characters, please note that the encoding format must be UTF-8 when saving the source file. Especially under Windows, general editors save as local encoding by default. For example, in China, it may be GBK encoding instead of UTF-8. If you don't pay attention to this, some unexpected situations will occur during compilation and runtime.

String encoding conversion is a very common requirement when processing text documents (such as TXT, XML, HTML, etc.). However, the Go language only supports UTF-8 and Unicode encoding by default. For other encodings, the Go language standard library does not have built-in encoding. Conversion support. Fortunately, we can easily wrap one based on the iconv library. Here is an open source project for reference: https://github.com/qiniu/iconv.

String operations
1. Connect
str := "hello"
str = str + ", continue"  // hello, continue
str += str //hellohello

string.Join()

s := strings.Join([2]string{"ajwlf","20"}, ",")  

buffer.WriteString() Efficiency is relatively high

var buffer bytes.Buffer
buffer.WriteString("ajwlf");
buffer.WriteString(",");
buffer.WriteString("20");
fmt.Printf("%s", buffer.String())  //ajwlf,20
2. Slice
str = "hello, world"
str_1 := str[:5]  // 获取索引5(不含)之前的子串
str_2 := str[7:]  // 获取索引7(含)之后的子串
str_3 := str[0:5]  // 获取从索引0(含)到索引5(不含)之间的子串
fmt.Println(str_1)
fmt.Println(str_2)
fmt.Println(str_3)

The above code prints the following results:

hello
world
hello
3. Traverse

The first way: byte array traversal

str := "Hello, 世界" 
n := len(str) 
for i := 0; i < n; i++ {
    ch := str[i]    // 依据下标取字符串中的字符,类型为byte
    fmt.Println(i, ch) 
}

The output of this example is:

0 72 
1 101 
2 108 
3 108 
4 111 
5 44 
6 32 
7 228 
8 184 
9 150 
10 231 
11 149 
12 140

As you can see, the length of this string is 13, although intuitively, this string should only be 9 characters. This is because each Chinese character occupies 3 bytes in UTF-8 instead of 1 byte.

Second way: Unicode traversal

str := "Hello, 世界" 
for i, ch := range str { 
    fmt.Println(i, ch)    // ch 的类型为 rune 
}

At this time, only 9 characters are printed. When traversing in Unicode character mode, the type of each character is rune(the early Go language used inttypes to represent Unicode characters), not byte.

4.Common operations

len(str): Find the length

+ 或 fmt.Sprintf(): concatenate strings

strings.Split(): split string

strings.Contains(): Determine whether it contains

strings.HasPrefix() 或 stings.HasSuffix()Judgment of suffixes and suffixes

strings.Index() 或 strings.LastIndex()The position where the string appears

strings.Join(a[] string, seq string)join operation

3. Derived types

An array is a collection of data of the same data type stored in memory in an orderly manner

Features

  • The length is fixed and cannot be modified.
  • The process of assignment and function transfer is value copying, involving memory cop.
(1)Array

Declaration method:var name [size]varType

var arr= [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}  
var arr1 [6]int
arr:=[5]int{1,2,3,4,5}
//如果设置了数组的长度,我们还可以通过指定下标来初始化元素:

var arr1 = [5]float32{1: 2.0, 3: 1323.0}

When the array length is uncertain:

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

How to declare a multidimensional array:var var_name[size1][size2]....[sizeN] varType

a := [3][4] int{  
    {0, 1, 2, 3} ,   /*  第一行索引为 0 */
    {4, 5, 6, 7} ,   /*  第二行索引为 1 */
    {8, 9, 10, 11},   /* 第三行索引为 2 */
 
    //注意:以上代码中倒数第二行的 } 必须要有逗号,因为最后一行的 } 不能单独一行,也可以写成这样:  

}

The go language also supports creating multi-dimensional arrays with inconsistent numbers of elements.

package main
 
import "fmt"
 
func main() {
    
    
    // 创建空的二维数组
    animals := [][]string{
    
    }
 
    // 创建三一维数组,各数组长度不同
    row1 := []string{
    
    "fish", "shark", "eel"}
    row2 := []string{
    
    "bird"}
    row3 := []string{
    
    "lizard", "salamander"}
 
    // 使用 append() 函数将一维数组添加到二维数组中
    animals = append(animals, row1)
    animals = append(animals, row2)
    animals = append(animals, row3)
 
    // 循环输出
    for i := range animals {
    
    
        fmt.Printf("Row: %v\n", i)
        fmt.Println(animals[i])
    }
}
(2) Slice
切片(slice)是一组具有相同数据类型在内存中有序存储的可扩容的数据集合

Declaration method:

var 切片名 []数据类型
var slice []int    //此时切片只是一个nil,还没有开辟空间。
make([]数据类型,长度)
var slice []int = make([]int, 10) //会开辟传入的大小的空间

We can find the length and capacity of our slice through the sum function (the length is how many elements are stored in our current slice, and the capacity is the maximum number of elements that the slice can hold. len() )cap()

  • Slice interception

When slicing is intercepted, the new slice returned points to the memory address of the original slice . It feels similar to a shallow copy. Changing the value of the intercepted slice will also change the value of the original slice synchronously.

func main() {
	//切片的截取
	slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
 
	//切片名[起始下标:结束下标:容量]  左闭右开 包含起始下标 不包含结束下标
	//s := slice[2:7]
	//fmt.Println(s)
	//s:=slice[2:]
	//fmt.Println(s)
	//s:=slice[:5]
	//fmt.Println(s)
	s := slice[2:5:6] //实际容量=容量-起始下标
	fmt.Println(s)
	//fmt.Println(len(s))
	//fmt.Println(cap(s))
	s[0] = 333
	//切片的截取 是将新的切片指向源切片的内存地址  修改一个会影响另外一个
	fmt.Println(s)
	fmt.Println(slice)
 
	fmt.Println(unsafe.Sizeof(slice))
	fmt.Println(unsafe.Sizeof(s))
}
  • Add element

Encountered error: append(s, 6) (value of type []int) is not used

s := append(s, 6) --> s = append(s, 6)

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5}
	s = append(s, 6)
	s = append(s, 7, 8)

	fmt.Printf("s: %v\n", s)

	s2 := []int{3, 4, 5}
	s3 := []int{6, 7, 8}

	s3 = append(s2, s3...)  //添加另外一个切片
	fmt.Printf("s3: %v\n", s3)

}

out:

s: [1 2 3 4 5 6 7 8]
s3: [3 4 5 6 7 8]
  • Delete element
func main() {
	index := 1
	s := []int{1, 2, 3, 4, 5}
	s = append(s[:index], s[index+1:]...) //删除s[index]	
	fmt.Printf("s: %v\n", s)

}

//out: s: [1 3 4 5]


Please add image description

func main() {

	s := []int{1, 2, 3, 4, 5}
	s3 := []int{}
	s4 := make([]int, 5)
	copy(s3, s)
	copy(s4, s)
	fmt.Printf("s: %v\n", s)
	fmt.Printf("s3: %v\n", s3)
	fmt.Printf("s4: %v\n", s4)

}
/*
	copy( destSlice, srcSlice []T) int
    其中 srcSlice 为数据来源切片,destSlice 为复制的目标(也就是将 srcSlice 复制到 destSlice),目标切片必须分配过空间且足够承载复制的元素个数,并且来源和目标的类型必须一致,copy() 函数的返回值表示实际发生复制的元素个数。
*/
(3)map
  • Declaration assignment of map

Declaration method:var map_variable map[key_data_type]value_data_type

m1 := map[string]string{
		"name": "zhangsan",
		"age":  "22",
	}
	fmt.Println(m1)
 
	m2 := make(map[string]int) //m2 == empty map
 
	var m3 map[string]int //m3 == nil
 
	fmt.Print(m2, m3)
 
	fmt.Print("遍历...\n")
	for i, v := range m1 {
		fmt.Println(i, v)
	}
  • The bottom layer is based on Hash implementation, based on Key-Value, unordered data collection

  • Function types, dictionary types and slice types cannot be used as keys. Unsupported operation types will cause panic.

  • Check whether the value exists

name := m1["name"]
fmt.Println(name)
//可以返回一个ok值 判断我们的key是否正确
nema, ok := m1["nema"] //找不到这个键 就会返回false
fmt.Print(nema, ok)
//所以可以改进代码
if name, ok := m1["name"]; ok == true {
    
    
    fmt.Println(name)
}
  • var m map[string]int// nil type, addition and modification will cause panic
  • nil: len/map[key]/delete(m, key)// works fine
  • By default, map concurrency is unsafe. Multiple goroutines writing the same map will cause a race error, go run –raceorgo build - race
  • Even if all keys of the map object are deleted, the space will not be reduced.
(5)Pointer

Whenever data is stored in memory, it is assigned a memory address. Memory addresses are represented using hexadecimal data.
Memory assigns each byte a 32-bit or 64-bit number (depending on the 32-bit or 64-bit processor).
You can use the operator & (address operator) to get the memory address of the data.

func main() {
	a := 10
	//取出变量a在内存的地址
	//fmt.Println(&a)
	var p *int = &a
	//fmt.Println(p)
	//fmt.Println(&a)
	//通过指针间接修改变量的值
	*p = 132
	fmt.Println(a)
 
	//const MAX int = 100
	//fmt.Println(&MAX)//err 不可以获取常量的内存地址
}
func main() {
	//定义指针 默认值为nil 指向内存地址编号为0的空间  内存地址0-255为系统占用 不允许用户读写操作
	//var p *int = nil
	//*p = 123 //err
	//fmt.Println(*p)
 
	//开辟数据类型大小的空间 返回值为指针类型
	//new(数据类型)
	var p *int
	p = new(int)
	*p = 123
	fmt.Println(*p)
}

Guess you like

Origin blog.csdn.net/qq_40893490/article/details/127770133