• Go基础-2


    1. 字符串常用操作

    方法介绍
    len(str)求长度
    strings.Split分割
    strings.Contains判断是否包含
    strings.HasPrefix,strings.HasSuffix前缀/后缀判断
    strings.Index(),strings.LastIndex()子串出现的位置

    1.1 字符串连接

    1. 加号连接
    2. func fmt.Sprintf(format string,a…interface{}) string
    3. func strings.Join(elems []string,sep string) string
    4. 当大量的string需要拼接时,用strings.Builder效率最高

    2. byte和rune

    string中每个元素叫"字符",字符有两种

    1. byte 1个字节,代表ascII码的一个字符
    2. rune 4个字节,代表一个utf-8字符,一个汉字可用一个rune表示

    string底层是byte数组,string的长度就是该byte数组的长度,utf-8编码下一个汉字占3个byte,即一个汉字占3个长度.

    string可以转换为[]byte或[]rune类型

    string是常量,不能修改其中的字符.

    3. 类型转换

    byte和int客户互相转换,但byte默认是uint8所以超出255之后就会转换出错.

    float和int可以互相转换,但小数点后会丢失

    bool和int不能互相转换

    不同长度的int或float之间可以相互转换

    string可以转换为[]byte或[]rune类型,byte或rune可以转换为string

    低精度向高精度转换没问题,高精度向低精度转换会丢失位数

    无符号向有符号转换,最高位是符号位

    4. 数组

    第一: 长度固定

    第二: 连续的内存空间

    第三: 同一类型的集合

    数组是块连续的内存空间,在声明的时候必须指定长度,且长度不能改变.所以数组在声明的时候就可以把内存空间分配好,并赋上默认值即完成了初始化.

    var arr1 [5]int = [5]int{}
    var arr2 = [5]int{}
    var arr3 = [5]int{3,2}
    var arr4 = [5]int{2: 15,3: 20}
    var arr5 = [...]int{3,2,4,5,9}
    var arr6 = [5][3]int{{1,2},{3}}
    var arr7 = [...][3]int{{1},{2,3}}	// 2行3列 第一个行可以...第二个列不能...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    首元素: arr[0]
    末元素: arr[len(arr)-1]
    二维数组: arr[2][3]
    
    • 1
    • 2
    • 3

    一维数组

    var arr1 = [...]int{1, 2, 4, 6, 7, 8, 9}
    	// 方法1:
    	for i, ele := range arr1 {
    		fmt.Printf("index=%d, element=%d\n", i, ele)
    	}
    	// 方法2:
    	for i :=0;i< len(arr1);i++ {
    		fmt.Printf("index=%d, element=%d\n", i, arr1[i])
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    二维数组

    	var arr2 = [...][4]int{{4,5,7},{0,2},{1,3,4,6}}
    	for row,array3 := range arr2 {
    		for col, ele := range array3 {
    			fmt.Printf("arr[%d][%d]=%d\n",row,col,ele)
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    求平均数

    func Avg1() {
    	var arr1 = [...]int{33,56,78,44,78,49,98,36,87}
    	var count int = 0
    	for i:=0;i<len(arr1);i++ {
    		count += arr1[i]
    	}
    	fmt.Printf("平均数等于=%f",float32(count)/float32((len(arr1))))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5. cap和len

    cap代表capacity容量

    len代表length长度

    len代表目前数组里面的几个元素,cap代表给数组分配的内存空间可以容纳多少个元素

    由于数组初始化之后长度不会改变,不需要给他预留内存空间,所以len(arr)==cap(arr)

    6. 数组传参

    数组的长度和类型都是数组类型的一部分,函数传递数组类型时这两部分都必须吻合

    go语言没有按引用传参,全部是按值传参,即传递数组实际上是进行数组的拷贝,当数组的长度很大时,传参开销都很大

    如果想修改函数外部数组,就把他的指针传进来.

    7. 修改字符串

    1. 将字符串转换成rune
    2. 切片获取原始数据
    3. 使用string()将byte数组转换成字符串

    byte和rune类型都是字符串

    byte表示的是ascii码,ASCII不能直接表示中文

    rune表示utf-8码(一个中文3个字节,一个英文是1个字节)

    7.1 字符串长度

       s := "hello world"
       fmt.Println(len(s))
       s_zh := "你好中国"
       fmt.Println(len(s_zh))
    结果:
       11
       12
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7.2 字符串拼接

    	s := "hello world"
    	s_zh := "你好中国"
    	s_new := s_zh + s
    	fmt.Println(s_new)
    结果:
    	你好中国hello world
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    7.3 字符串转数组

    	str := "22+11+38"
    	arr1 := strings.Split(str, "+")
    	fmt.Printf("%T:%v", arr1, arr1)
    结果:
    	[]string:[22 11 38]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    7.4 数组转字符串

    	str2 := strings.Join(arr1, "-")
    	fmt.Printf("%T:%v", str2, str2)
    结果:
    	string:22-11-38 
    
    • 1
    • 2
    • 3
    • 4

    7.5 单引号字符串

    单引号只能表示一个字符

    	a := 'a'		//正确
    	a1 := 'aa'		//错误
    
    • 1
    • 2

    7.6 遍历字符串

    	s := "hello 中国"
    	for _, val := range s {
    		fmt.Printf("%T:%v:%c\n", val, val, val)
    	}
    结果:
        int32:104:h
        int32:101:e   
        int32:108:l   
        int32:108:l   
        int32:111:o   
        int32:32:     
        int32:20013:中
        int32:22269:国
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    7.7 数字转字符

    	// 1. 数字转成字符串
    	num := 100
    	fmt.Printf("%T:%d\n", num, num)
    	strNum := strconv.Itoa(num)
    	fmt.Printf("%T:%s\n", strNum, strNum)
    结果:
    	int:100
    	string:100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.8 字符转数字

    字符转数字时可能会有err,需要加一段if避免报错中断

    	// 2. 字符串转数字
    	intNum, err := strconv.Atoi(strNum)
    	if err != nil {
    		fmt.Print(err)
    	}
    	fmt.Printf("%T:%d", intNum, intNum)
    结果:
    	int:100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    8. 切片

    切片和数组区别: 切片长度不固定,可以根据需求自动扩容.数组长度固定

    切片包括,地址,长度,容量

    数组包含两个标识:地址,长度没有容量

    第一. 长度可变

    第二. 连续内存空间

    第三.同一类型集合

    //切片
    a := []string{"sh","bj","hz"}
    //数组
    b := [...]string{"西安","吉林","无锡"}
    c := [3]int{1,2,3}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    拥有相同类型的可变长度的集合

    切片之间不能比较

    切片的本质就是对底层数组的封装,它包含了三个信息.底层数组的 指针,切片的长度(len),切片的容量(cap)

    s1内存了: 指针–>开始位置,长度 3,容量8.只是对原有数据的引用

    长度就是不算当前位置,到结尾有多少个.

    容量就是算当前位置,到数组末尾有多少个位置

    	b := [8]int{1, 2, 3, 4, 5, 6, 7, 8}
    	s1 := b[3:6]
    	fmt.Println(s1)
    	fmt.Printf("长度%v,容量%v\n", len(s1), cap(s1))
    	结果:
    	[4 5 6]     
    	长度3,容量5 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    	b := [8]int{1, 2, 3, 4, 5, 6, 7, 8}
    	s1 := b[0:5]
    	fmt.Println(s1)
    	fmt.Printf("长度%v,容量%v\n", len(s1), cap(s1))
    	结果:
    	[1 2 3 4 5] 
    	长度5,容量8 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    8.1 切片的循环

    两种切片方法.

    	b := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    	s1 := b[2:8]
    	fmt.Println(s1)
    	fmt.Printf("长度%v,容量%v\n", len(s1), cap(s1))
    	for i := 0; i < len(s1); i++ {
    		fmt.Println(s1[i])
    	}
    	for _, value := range s1 {
    		fmt.Println(value)
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    8.2 切片追加元素

    	y := []int{1, 2}
    	y = append(y, 6, 7, 8)
    	fmt.Println(y)
    	fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
    	结果:
    	[1 2 6 7 8]
    	长度:5,容量:6
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    8.3 切片合并

    	z := []int{99, 88}
    	y := []int{1, 2}
    	y = append(y, 6, 7, 8)
    	fmt.Println(y)
    	fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
    	// 合并z和y
    	y = append(y, z...)
    	fmt.Println(y)
    	fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
    	结果
    	[1 2 6 7 8]
        长度:5,容量:6
        [1 2 6 7 8 99 88]
        长度:7,容量:12
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    8.4 切片删除元素

    	z := []int{99, 88}
    	y := []int{1, 2}
    	y = append(y, 6, 7, 8)
    	fmt.Println(y)
    	fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
    	// 合并z和y
    	y = append(y, z...)
    	fmt.Println(y)
    	fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
    	// 删除切片中的第二个元素
    	y = append(y[:1], y[2:]...)
    	fmt.Println(y)
    	fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
    	结果
    	[1 2 6 7 8]
        长度:5,容量:6
        [1 2 6 7 8 99 88]
        长度:7,容量:12
        [1 6 7 8 99 88]
        长度:6,容量:12
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    9. 字典Map

    1. 无序
    2. key,value
    3. 必须初始化才能使用

    9.1 定义map

    	userinfo := map[string]int{
    		"张三": 11,
    		"李四": 78,
    	}
    	fmt.Println(userinfo)
    	结果
    	map[张三:11 李四:78]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    9.2 判断map中的key是否存在

    	userinfo := map[string]int{
    		"张三": 11,
    		"李四": 78,
    	}
    	fmt.Println(userinfo)
    	// 判断key是否存在
    	val, ok := userinfo["张三"]
    	fmt.Println(val, ok)
    	val, ok = userinfo["zhangsan"]
    	fmt.Println(val, ok)
    	结果
    	11 true
    	0 false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    9.3 结合if

    userinfo := map[string]int{
    		"张三": 11,
    		"李四": 78,
    	}
    	fmt.Println(userinfo)
    	// 判断key是否存在
    	val, ok := userinfo["张三"]
    	//fmt.Println(val, ok)
    	//val, ok = userinfo["zhangsan"]
    	fmt.Println(val, ok)
    	if ok {
    		fmt.Println(val, ok)
    	} else {
    		fmt.Println("该数据不存在")
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    或者

    	userinfo := map[string]int{
    		"张三": 11,
    		"李四": 78,
    	}
    	// 判断key是否存在
    	if val, ok := userinfo["张三"]; ok {
    		fmt.Println(val, ok)
    	} else {
    		fmt.Println("该数据不存在")
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    9.4 删除map中的一个数据

    	fmt.Println(userinfo)
    	delete(userinfo, "李四")
    	fmt.Println(userinfo)
    	结果
    	map[张三:11 李四:78]
    	map[张三:11]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    9.5 遍历map

    方法1:

    	// 定义map
    	userInfo := map[string]int{
    		"zhangsan":   22,
    		"liudehua":   52,
    		"lixiaolong": 68,
    		"luban":      250,
    	}
    	// 1. for range 遍历key
    	for k := range userInfo {
    		if val, ok := userInfo[k]; ok {
    			fmt.Println(k, val)
    		}
    	}
    	结果
    	zhangsan 22
        liudehua 52  
        lixiaolong 68
        luban 250    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    方法2:

    	for key1, value1 := range userInfo {
    		fmt.Println(key1, value1)
    	}
    	结果
    	zhangsan 22
        liudehua 52  
        lixiaolong 68
        luban 250    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    10. 指针

    • 指针地址(&a)
    • 指针取值(*&a)
    • 指针类型(&a)

    第一步,定义变量
    第二步,内存中申请一块空间,用来存放变量的值
    第三步,要得到变量的值,先获取到变量的内存地址

    	a := 100
    	fmt.Println(&a)
    	结果
    	0xc0000a6058		//这个就是变量a的内存地址
    
    • 1
    • 2
    • 3
    • 4

    取出内存中的值

    	a := 100
    	fmt.Println(&a)
    	fmt.Printf("%d\n", &a)
    	b := &a
    	fmt.Println(*b)
    	结果
    	0xc0000a6058
        824634400856
        100  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    获取指针类型

    *int是指针类型,0xc0000180c8是内存地址位置

    	fmt.Printf("%T:%v\n", &a, &a)
    	结果
    	*int:0xc0000180c8
    
    • 1
    • 2
    • 3

    10.1 new和make

    通过make方法申请空间使用

    	//默认长度是3,默认容量是10
    	t := make([]int, 3, 10)
    	fmt.Println(t)
    	fmt.Println(len(t), cap(t))
    	结果
    	[0 0 0]
    	3 10    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    通过new方法申请空间

    make创建的是值类型,new创建的是指针类型

    	t := make([]int, 3, 10)
    	v := new([]int)
    	fmt.Printf("make:%T new:%T", t, v)
    	结果
    	make:[]int new:*[]int
    
    • 1
    • 2
    • 3
    • 4
    • 5

    make和new的区别:

    • make关键字的作用是创建slice,map和channel等内置的数据结构
      • make只能对内置数据类型进行申请内存
      • 返回时,数据本身
    • new 的作用是为类型申请一片内存空间,并返回指向这片内存的指针
      • new方法主要是给struct等非内置数据类型申请空间
      • 返回一个指针类型
  • 相关阅读:
    内核编译 --- 链接器
    腾讯mini项目-【指标监控服务重构】2023-08-26
    HTML躬行记(4)——Web音视频基础
    Mybatis源码解析(五):SqlSession会话的创建
    阿里云体验有奖:使用PolarDB-X与Flink搭建实时数据大屏
    176. 装满的油箱 图 - 拆点
    菇多糖-聚乙二醇-大环配体NOTA,大环配体NOTA-PEG-香菇多糖
    Linux【操作系统】
    SQL面试题之区间合并问题
    Springboot毕设项目保险理赔管理系统312z6(java+VUE+Mybatis+Maven+Mysql)
  • 原文地址:https://blog.csdn.net/qq_29974229/article/details/128196358