KittyDaddy's blog KittyDaddy's blog
首页
  • 学习笔记

    • 《Java基础》
    • 《常用设计模式》
    • 《MYSQL》
    • 《GO语言》
    • 《Spring源码解读》
  • 微服务解决方案

    • 锁的演化
    • 简单限流方案
    • 海量数据切分
  • 中间件

    • Nginx
    • MQ
    • Redis
    • Keepalived
  • 面试记
  • 杂文
  • 开源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

老猫

万物皆系统
首页
  • 学习笔记

    • 《Java基础》
    • 《常用设计模式》
    • 《MYSQL》
    • 《GO语言》
    • 《Spring源码解读》
  • 微服务解决方案

    • 锁的演化
    • 简单限流方案
    • 海量数据切分
  • 中间件

    • Nginx
    • MQ
    • Redis
    • Keepalived
  • 面试记
  • 杂文
  • 开源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 跟着老猫一起来学GO,上车!
  • 跟着老猫一起来学GO,环境搭建
  • 跟着老猫来搞GO,基础语法熟悉
  • 跟着老猫来搞GO,基础进阶
  • 跟着老猫来搞GO,容器
  • 跟着老猫来搞GO-容器(2)
    • 跟着老猫来搞GO-面向对象
    • 《Go语言》
    老猫
    2021-11-21
    目录

    跟着老猫来搞GO-容器(2)

    # 前期回顾

    在上面的文章中,老猫和大家分享了GO语言中比较重要的两种数据结构,一种是数组,另外一种是基于数组的slice。本篇文章想要继续和大家分享剩下的容器以及字符字符串的处理。

    # MAP

    # map的定义

    在Java语言中其实还有一个键值对的容器,叫做Map,当然在我们GO语言中也有这种数据结构,例如,下面咱们就来看一下GO语言中Map的写法以及用法。看下一Map的语法定义,如下例子:

    m :=map[string]string {
    		"name":"ktdaddy",
    		"age":"28",
    		"job":"softEngineer",
    }
    
    1
    2
    3
    4
    5

    关于语法的定义其实也是比较简单的,方括号里面的表示key值,后面的那个类型表示value的类型。上面老猫其实定义了一个map,并且给它初始化了一些数据。定义一个空的map其实也是比较简单的,主要有下面两种方式

    m1 :=make(map[string]int) //采用make函数直接创建一个map,比较常用
    var m2 map[string] int //用var函数申明的方式创建map
    
    1
    2

    说实在的语法这种东西也没法说出什么所以然来,大家既然想要学习这个语言就要去记下它的规则,所以还是得多写多练,长时间不去用可能就忘记了。

    总结一下其定义形式map[k]V,当然咱们也可以定义它比较复杂一些的数据结构,例如map里面套map,这种复合型的,那么定义的最终形式就是map[K1]map[K2]V。

    # 对map的操作

    # 查询元素

    我们定义出一个map之后,正常的逻辑就要去操作这个map,咱们先来看一下如何遍历一个map,我想大家比较容易想到的就是我们讲array的时候用的range函数的方式。确实,咱们可以写成这样,咱们就以一开始定义的m这个Map为例吧

    for k,v :=range m {
    	fmt.Println(k,v)
    }
    
    1
    2
    3

    这样我们就可以获取所有的数据,当然我们也可以根据对应的Key值获取相关的value

    name :=m["name"]
    
    1

    但是很多时候,我们是不能知道这个key是否存在的,我们取值的时候就要先判断当前的key是否存在,然后再去获取值,其实我们可以这样写

    name,ok :=m["name"]
    fmt.Println(name,ok) //结果输出ktdaddy true
    
    1
    2

    很显然,我们可以通过ok的值去判断当前的key是否存在,然后再去获取其中的value值。那么结合前面所讲的if条件语句,咱们就可以写出这样的逻辑

    if name,ok :=m["name"];ok {
    	fmt.Println(name)
    }else {
    	fmt.Println("key does not exist")
    }
    
    1
    2
    3
    4
    5
    # 删除元素

    删除元素其实是相当简单的,用内置函数delete函数即可。我们还是承接上面的逻辑,如果发现存在这个Key值,那么我们就从map中进行移除。具体如下

    if name,ok :=m["name"];ok {
    		delete(m,"name")
    		name,ok = m["name"]
    		fmt.Println(name,ok)
    	}else {
    		fmt.Println("key does not exist")
    }
    
    1
    2
    3
    4
    5
    6
    7

    上述删除之后咱们重新赋值map,这样这个代码最终输出的结果就是false。大家可以实际动手练习一下。

    # 字符串的处理

    老猫想过好几次,如何写这个字符串,想要将其单独抽出来说感觉也不合适,因为咱们很多时候会遍历容器中的字符,因此索性就将其合并在内建容器里面一起分享好了。这里主要想和大家分享的是rune这个内建类型,从前面的章节中我们都知道这个相当于是Go的char,那么这个又怎么来用呢?咱们先来看下面例子

    s:= "hello我爱GO开发"
    fmt.Println(len(s))
    
    1
    2

    大家觉得这个应该会输出多少呢?试着运行一下,答案是19,那么为什么呢?我们再接着转换成字节输出一下

    s:= "hello我爱GO开发"
    fmt.Println(s)
    fmt.Println(len(s))
    fmt.Printf("%X\n",[]byte(s))
    
    1
    2
    3
    4

    这样呢,我们就获取一段16进制的字节,结果如下

    68656C6C6FE68891E788B1474FE5BC80E58F91
    
    1

    很显然,我们还是无法看出来,我们将其格式做一下分割调整来看一下

    s:= "hello我爱GO开发"
    fmt.Println(s)
    fmt.Println(len(s))
    fmt.Printf("%X\n",[]byte(s))
    
    for _,b:=range []byte(s) {
        fmt.Printf("%X ",b)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    运行的结果为 :68 65 6C 6C 6F E6 88 91 E7 88 B1 47 4F E5 BC 80 E5 8F 91

    数一下成对出现的16进制数,咱们就可以发现19个字节长度原来是这么来的。通过分析我们不难发现一个英文占用了两个字节而中文则占用了3个字节,例如里面的“我”转换之后就是:E6 88 91,那么我们直接输出s又会是什么呢?

    for i,ch := range s{ // ch is a rune
    	 	fmt.Printf("(%d %X) ",i,ch)
    }
    fmt.Println()
    
    1
    2
    3
    4

    结果为:

    (0 68) (1 65) (2 6C) (3 6C) (4 6F) (5 6211) (8 7231) (11 47) (12 4F) (13 5F00) (16 53D1) 
    
    1

    其实通过68 65 6C 6C 6F E6 88 91 E7 88 B1 47 4F E5 BC 80 E5 8F 91 转换成了上面这个是通过什么转换的呢?其实通过utf-8转换成了unicode编码,我们发现转换成unicode之后,相关的中文字符编程了长度为4的16进制数,那么其实就是相当于是rune所占的字节长度了。

    所以我们直接用rune对其进行转换。

    for i,ch :=range []rune(s){
    		fmt.Printf("(%d %c)",i,ch)
    }
    
    1
    2
    3

    这样我们就得到了如下

    (0 h)(1 e)(2 l)(3 l)(4 o)(5 我)(6 爱)(7 G)(8 O)(9 开)(10 发)
    
    1

    如此,其实就遍历获取到了每个字符了。

    当然,如果我们要统计utf-8下的字符长度,其实我们要对其进行转换,在此介绍两个函数

    utf8.RuneCountInString(s)
    utf8.DecodeRune(bytes)
    
    1
    2

    通过这两个函数,咱们可以获取中文字符下的具体的字符个数了。

    看起来比较零碎,咱们做一下总结,当然剩下还是得大家自己写一下。

    1. 使用range遍历pos,rune对
    2. 使用utf8.RuneCountInString(s)获取字符数量
    3. 使用len获取字节长度
    4. 使用[]byte获取字节

    # 总结

    本次主要和大家分享了内建容器的剩余部分map的定义以及相关的操作使用,后面还和大家穿插了部分字符串的处理方式,当然还是比较散的,后面在写项目的过程中,咱们到时候在具体用起来,所以在此希望大家持续关注老猫,另外的也希望大家多练习,一起进步,加油。

    上次更新: 2022/11/30, 00:06:25
    跟着老猫来搞GO,容器
    跟着老猫来搞GO-面向对象

    ← 跟着老猫来搞GO,容器 跟着老猫来搞GO-面向对象→

    最近更新
    01
    让大龄程序员欲罢不能的事儿
    09-23
    02
    运营明明设置了活动开始时间,为什么到点没生效?聊聊动态定时任务
    07-30
    03
    不是,大哥,咱这小门小户的,别搞我CDN流量啊
    07-25
    更多文章>
    Theme by Vdoing | Copyright © 2020-2024 Kitty Daddy | License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式