当前位置: 首页 > news >正文

三 Go的语言容器

1. 数组

数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。因为数组的长度是固定的,所以在Go语言中很少直接使用数组

声明语法:
var 数组变量名 [元素数量]Type
package main
import ("fmt"
)
func main() {var a [3]int             // 定义三个整数的数组,仅是定义,默认值是填0fmt.Println(a[0])        // 打印第一个元素fmt.Println(a[len(a)-1]) // 打印最后一个元素// 打印索引和元素for i, v := range a {fmt.Printf("%d %d\n", i, v)}for _, v := range a {fmt.Printf("%d\n", v)}var q = [...]int{1, 2, 3}var r = [3]int{1, 2}fmt.Println(q[1]) // "2"fmt.Println(r[2]) // "0"k := [...]int{1, 2, 3}v := [...]int{2, 3, 4}//m := [...]int{1, 2, 3, 4}fmt.Println(k == v) //false//fmt.Println(k == m) //不同类型无法进行比较var teams [3]stringteams[0] = "hello"teams[1] = "go"teams[2] = "!"for i, v := range teams {fmt.Printf("序号: %d 值: %s\n", i, v)}
}

2. 切片

2.1 定义切片

// 声明字符串切片
var strList []string
// 声明整型切片
var numList []int
// 声明一个空切片
var numListEmpty = []int{}
// 输出3个切片
fmt.Println(strList, numList, numListEmpty)
// 输出3个切片大小
fmt.Println(len(strList), len(numList), len(numListEmpty))
// 切片判定空的结果
fmt.Println(strList == nil)
fmt.Println(numList == nil)
fmt.Println(numListEmpty == nil)

make构造切片

a := make([]int, 2)
b := make([]int, 2, 10)
fmt.Println(a, b)
fmt.Println(len(a), len(b))

2.2 为切片新增元素

package main
import "fmt"
var numbers []int
func main() {var a []intx := []int{1, 2, 3}a = append(a, 1)       // 追加1个元素a = append(a, 1, 2, 3) // 追加多个元素, 手写解包方式a = append(a, x...)    // 追加一个切片, 切片需要解包fmt.Println(a)deal()var b = []int{1, 2, 3}b = append([]int{0}, b...)          // 在开头添加1个元素fmt.Println(b)b = append([]int{-3, -2, -1}, b...) // 在开头添加1个切片fmt.Println(b)
}
func deal() {for i := 0; i < 10; i++ {numbers = append(numbers, i)fmt.Printf("len: %d  cap: %d pointer: %p\n", len(numbers), cap(numbers), numbers)}
}

2.3 切片复制

copy作用前面的切片元素,以小的切片元素为复制对象

package main
import "fmt"
func main() {slice1 := []int{1, 2, 3, 4, 5}slice2 := []int{5, 4, 3}copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中fmt.Println(slice1)  //[1 2 3 4 5]fmt.Println(slice2)  //[1 2 3]slice2 = []int{7, 8, 9}copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置fmt.Println(slice1)  //[7 8 9 4 5]
}
package main
import "fmt"
func main() {// 设置元素数量为1000const elementCount = 1000// 预分配足够多的元素切片srcData := make([]int, elementCount)// 将切片赋值for i := 0; i < elementCount; i++ {srcData[i] = i}// 引用切片数据refData := srcData// 预分配足够多的元素切片copyData := make([]int, elementCount)// 将数据复制到新的切片空间中copy(copyData, srcData)// 修改原始数据的第一个元素srcData[0] = 999// 打印引用切片的第一个元素fmt.Println(refData[0])// 打印复制切片的第一个和最后一个元素fmt.Println(copyData[0], copyData[elementCount-1])// 复制原始数据从4到6(不包含)copy(copyData, srcData[4:6])for i := 0; i < 5; i++ {fmt.Printf("%d ", copyData[i])}
}

代码说明如下:

  • 第 8 行,定义元素总量为 1000。
  • 第 11 行,预分配拥有 1000 个元素的整型切片,这个切片将作为原始数据。
  • 第 14~16 行,将 srcData 填充 0~999 的整型值。
  • 第 19 行,将 refData 引用 srcData,切片不会因为等号操作进行元素的复制。
  • 第 22 行,预分配与 srcData 等大(大小相等)、同类型的切片 copyData。
  • 第 24 行,使用 copy() 函数将原始数据复制到 copyData 切片空间中。
  • 第 27 行,修改原始数据的第一个元素为 999。
  • 第 30 行,引用数据的第一个元素将会发生变化。
  • 第 33 行,打印复制数据的首位数据,由于数据是复制的,因此不会发生变化。
  • 第 36 行,将 srcData 的局部数据复制到 copyData 中。
  • 第 38~40 行,打印复制局部数据后的 copyData 元素。

2.4 切片删除元素

2.4.1 开头元素

特性

a := []int{1, 2, 3}
a = a[1:] // 删除开头1个元素
a = a[N:] // 删除开头N个元素

append

a = []int{1, 2, 3}
a = append(a[:0], a[1:]...) // 删除开头1个元素
a = append(a[:0], a[N:]...) // 删除开头N个元素

copy

a = []int{1, 2, 3}
a = a[:copy(a, a[1:])] // 删除开头1个元素
a = a[:copy(a, a[N:])] // 删除开头N个元素

2.4.2 中间删除

a = []int{1, 2, 3, ...}
a = append(a[:i], a[i+1:]...) // 删除中间1个元素
a = append(a[:i], a[i+N:]...) // 删除中间N个元素
a = a[:i+copy(a[i:], a[i+1:])] // 删除中间1个元素
a = a[:i+copy(a[i:], a[i+N:])] // 删除中间N个元素

2.4.3 末尾删除

a := []int{1, 2, 3}
a = a[:len(a)-1] // 删除尾部1个元素
a = a[:len(a)-N] // 删除尾部N个元素

2.4.4 指定元素删除

package main
import "fmt"
func main() {list1 := []int{1, 2, 3, 3, 5, 4}list2 := []int{1, 2, 3, 3, 5, 4}list1 = DeleteSlice3(list1, 3)fmt.Println(list1)list3 := DeleteSlice2(list2, 3)fmt.Println(list3)
}
// DeleteSlice3 位移法
func DeleteSlice3(a []int, elem int) []int {j := 0for _, v := range a {if v != elem {a[j] = vfmt.Println(a)j++}}return a[:j]
}
// DeleteSlice2 拷贝法
func DeleteSlice2(a []int, elem int) []int {tmp := make([]int, 0, len(a))for _, v := range a {if v != elem {tmp = append(tmp, v)}}return tmp
}位移法输出:
[1 2 3 3 5 4]
[1 2 3 3 5 4]
[1 2 5 3 5 4]
[1 2 5 4 5 4]
[1 2 5 4]解析:把后面不等于3的元素提前,然后根据最后j的长度来返回需要取多长,同时把3元素排除拷贝法输出:
[1]
[1 2]
[1 2 5]
[1 2 5 4]
[1 2 5 4]
解析:这个就很好理解了,创建一个空的切片,值不等就添加进去

3. 映射

3.1 map概念

package main
import "fmt"
func main() {map1 := make(map[int]int)map1 = map[int]int{1: 3, 2: 4}fmt.Println(map1)for i, v := range map1 {fmt.Printf("键是: %d 值是: %d\n", i, v)}
}

3.2 遍历map

package main
import "fmt"
func main() {slice1 := make([]int, 0)slice1 = append(slice1, 1, 2, 3, 4)map1 := make(map[int]int)for i, v := range slice1 {map1[i] = v}fmt.Println(map1)
}注明:
for i, v := range 可输出键值
如果只需要键:
for i := range 
如果只需要值:
for _, v := range

3.3 map转slice排序

package main
import ("fmt""sort"
)
func main() {scene := make(map[string]int)// 准备map数据scene["route"] = 66scene["brazil"] = 4scene["china"] = 960// 声明一个切片保存map数据var sceneList []string// 将map数据遍历复制到切片中for k := range scene {sceneList = append(sceneList, k)}// 对切片进行排序sort.Strings(sceneList)  //对字符串进行排序// 输出fmt.Println(sceneList)
}

3.4 删除map中的元素

package main
import ("fmt"
)
func main() {scene := make(map[string]int)// 准备map数据scene["route"] = 66scene["brazil"] = 4scene["china"] = 960delete(scene, "brazil")for k, v := range scene {fmt.Println(k, v)}
}

ps: 使用字典就是用make函数重新创个新的即可,其余的交给GC回收机制

3.5 并发环境使用Map

sync.Map 有以下特性:

  • 无须初始化,直接声明即可。
  • sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。
  • 使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。

代码演示如下:

package main
import ("fmt""sync"
)
func main() {var scene sync.Map// 将键值对保存到sync.Mapscene.Store("greece", 97)scene.Store("london", 100)scene.Store("egypt", 200)// 从sync.Map中根据键取值fmt.Println(scene.Load("london"))// 根据键删除对应的键值对scene.Delete("london")// 遍历所有sync.Map中的键值对scene.Range(func(k, v interface{}) bool {fmt.Println("iterate:", k, v)return true})
}

代码说明如下:

  • 第 10 行,声明 scene,类型为 sync.Map,注意,sync.Map 不能使用 make 创建。
  • 第 13~15 行,将一系列键值对保存到 sync.Map 中,sync.Map 将键和值以 interface{} 类型进行保存。
  • 第 18 行,提供一个 sync.Map 的键给 scene.Load() 方法后将查询到键对应的值返回。
  • 第 21 行,sync.Map 的 Delete 可以使用指定的键将对应的键值对删除。
  • 第 24 行,Range() 方法可以遍历 sync.Map,遍历需要提供一个匿名函数,参数为 k、v,类型为 interface{},每次 Range() 在遍历一个元素时,都会调用这个匿名函数把结果返回。

4. 列表

列表创建与传值

package main
import ("container/list""fmt"
)
func main() {l := list.New()l.PushFront("hello")l.PushBack("world")element := l.PushBack("wo")l.InsertBefore("baby", element)l.InsertAfter("aiNi", element)l.Remove(element)for i := l.Front(); i != nil; i = i.Next() {fmt.Println(i.Value)}
}

5. 空值与零值

指针、切片、映射、通道、函数和接口的零值则是 nil

5.1 nil标识符不能比较

package main
import ("fmt"
)
func main() {fmt.Println(nil==nil)
}

运行结果: 未定义操作
PS D:\code> go run .\main.go
#command-line-arguments
.\main.go:8:21: invalid operation: nil == nil (operator == not defined on nil)

5.2 nil不是关键字和保留字

以下编写是可以通过编译的,但不推荐这么做
var nil = errors.New("my god")

5.3 nil没有默认类型

package main
import ("fmt"
)
func main() {fmt.Printf("%T", nil)print(nil)
}

输出:
#command-line-arguments
.\main.go:7:8: use of untyped nil in argument to print

5.4 不同类型 nil 的指针是一样的

package main
import ("fmt"
)
func main() {var arr []intvar num *intfmt.Printf("%p\n", arr)fmt.Printf("%p", num)
}

输出:
0x0
0x0
Process finished with the exit code 0

5.5 nil是map、slice、pointer、channel、func、interface 的零值

package main
import ("fmt"
)
func main() {var m map[int]stringvar ptr *intvar c chan intvar sl []intvar f func()var i interface{}fmt.Printf("%#v\n", m)fmt.Printf("%#v\n", ptr)fmt.Printf("%#v\n", c)fmt.Printf("%#v\n", sl)fmt.Printf("%#v\n", f)fmt.Printf("%#v\n", i)
}

输出:
PS D:\code> go run .\main.go
map[int]string(nil)
(*int)(nil)
(chan int)(nil)
[]int(nil)
(func())(nil)

5.6 不同类型的nil值占用的内存大小可能不一样

package main
import ("fmt""unsafe"
)
func main() {var p *struct{}fmt.Println( unsafe.Sizeof( p ) ) // 8var s []intfmt.Println( unsafe.Sizeof( s ) ) // 24var m map[int]boolfmt.Println( unsafe.Sizeof( m ) ) // 8var c chan stringfmt.Println( unsafe.Sizeof( c ) ) // 8var f func()fmt.Println( unsafe.Sizeof( f ) ) // 8var i interface{}fmt.Println( unsafe.Sizeof( i ) ) // 16
}

输出:
PS D:\code> go run .\main.go
8
24
8
8
8
16

相关文章:

三 Go的语言容器

1. 数组 数组是一个由固定长度的特定类型元素组成的序列&#xff0c;一个数组可以由零个或多个元素组成。因为数组的长度是固定的&#xff0c;所以在Go语言中很少直接使用数组 声明语法&#xff1a; var 数组变量名 [元素数量]Typepackage main import ("fmt" ) fu…...

2023年全国最新会计专业技术资格精选真题及答案16

百分百题库提供会计专业技术资格考试试题、会计考试预测题、会计专业技术资格考试真题、会计证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 一、单选题 1.下列各项关于会计监督职能的表述中&#xff0c;正确的是&#xff…...

模板进阶(仿函数,特化等介绍)

非类型模板参数 模板参数有类型形参和非类型形参&#xff1b; 类型形参&#xff1a;使用typename或者class修饰的参数类型名称 非类型形参&#xff1a;一个普通常量作为模板参数形参&#xff0c;不能为浮点数&#xff0c;字符类型以及类对象&#xff1b; #include<iostrea…...

Beats:在 Docker 中同时部署 Metricbeat 和 Elasticsearch

在本教程中&#xff0c;我们将部署一个 metricbeat 来监控正在运行的容器的健康状况和系统指标。 为什么需要监控&#xff0c;为什么需要 Metricbeat&#xff1f; 一个常见的问题&#xff0c;但很少有人回答。 首先&#xff0c;无论我们部署的是 docker 容器还是老式的金属箱&…...

编码技巧——Redis Pipeline

本文介绍Redis pipeline相关的知识点及代码示例&#xff0c;包括Redis客户端-服务端的一次完整的网络请求、pipeline与client执行多命令的区别、pipeline与Redis"事务"、pipeline的使用代码示例&#xff1b; pipeline与client执行多命令的区别 Redis是一种基于客户…...

ArcGIS制图技巧:制图入门与点、线、面状符号制作

目的&#xff1a; 1、了解地图制作目的&#xff1b; 2、了解在ArcMap平台中制作地图大致过程。 3、掌握地形图生成的操作&#xff1b; 4、掌握地形图的正确输出方法。 5、理解点状符号、线状符号、面状符号的基本概念&#xff1b; 6、理解地形点状符号、线状符号、面状符…...

Java基础 关于字典数据维护接口设计

开发环境 Eclipse2022JDK1.8 目录 1. 概述 2. 实现步骤 2.1 定义通用接口 2.2 定义实体类 2.3 接口扩展 2.4 接口实现 2.5 功能测试 3. 结语 1. 概述 每一个信息系统或多或少都带有一些数据字典&#xff0c;在维护上&#xff0c;基本上分为增删改查&#xff0c;也就是对数据…...

从零开始学架构——复杂度来源

复杂度来源——高性能 对性能孜孜不倦的追求是整个人类技术不断发展的根本驱动力。例如计算机,从电子管计算机到晶体管计算机再到集成电路计算机,运算性能从每秒几次提升到每秒几亿次。但伴随性能越来越高&#xff0c;相应的方法和系统复杂度也是越来越高。现代的计算机CPU集成…...

什么时候需要分表分库?

在当今互联网时代&#xff0c;海量数据基本上是每一个成熟产品的共性&#xff0c;特别是在移动互联网产品中&#xff0c;几乎每天都在产生数据&#xff0c;例如&#xff0c;商城的订单表、支付系统的交易明细以及游戏中的战报等等。对于一个日活用户在百万数量级的商城来说&…...

冰刃杀毒工具使用实验(29)

实验目的 &#xff08;1&#xff09;学习冰刃的基本功能&#xff1b; &#xff08;2&#xff09;掌握冰刃的基本使用方法&#xff1b;预备知识 windows操作系统的基本知识&#xff0c;例如&#xff1a;进程、网络、服务和文件等的了解。 冰刃是一款广受好评的ARK工…...

聊聊图像分割的DICE和IOU指标

目录 1. 介绍 2. dice 和 iou 的联系 3. 代码实现 3.1 dice 3.2 iou 3.3 test 3.4 dice 和 iou 的关系曲线 4. 代码 1. 介绍 dice 和 iou 都是衡量两个集合之间相似性的度量 dice计算公式&#xff1a; iou计算公式&#xff1a; iou的集合理解&#xff1a; iou 其实就…...

软件设计师教程(十)计算机系统知识-结构化开发

软件设计师教程 软件设计师教程&#xff08;一&#xff09;计算机系统知识-计算机系统基础知识 软件设计师教程&#xff08;二&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;三&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;…...

链表OJ之 快慢指针法总结

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; 前言&#xff1a; 快慢指针指的是每次指针移动的步长&#xff0c;是解决链表相关的题目的一大利器&#xff0c;下面我将以例题的形式讲解快慢指针法。 目录 一. 链表的中间结点 思路&#xff1a; 代码实…...

C++STL详解(五)——list的介绍与使用

文章目录list的介绍list的使用list的定义方法list迭代器失效问题list插入和删除inserteraselist迭代器的使用begin&#xff0c;end 和 rbegin&#xff0c;rendlist元素访问front 和 backlist容量控制与数据清理resizeclearlist操作函数spliceremove 和 remove_ifuniquemergerev…...

进程和进程的调度

今天,为大家带来进程和进程的调度的学习 1.认识计算机 2.什么是操作系统 3.什么是进程 4.进程管理 5.进程的属性 6.进程的调度 7.进程调度的过程 8.内存分配 1.认识计算机 计算机的组成有五大部分 1.CPU(是计算机的大脑,负责逻辑运算和控制) 2.内存 3.外存 4.输入…...

TypeScript 深度剖析:TypeScript 的理解?与 JavaScript 的区别?

一、是什么 TypeScript 是 JavaScript 的类型的超集&#xff0c;支持ES6语法&#xff0c;支持面向对象编程的概念&#xff0c;如类、接口、继承、泛型等 超集&#xff0c;不得不说另外一个概念&#xff0c;子集&#xff0c;怎么理解这两个呢&#xff0c;举个例子&#xff0c;如…...

美颜SDK关键技术讲解——人脸识别与人脸美化

拍摄&#xff0c;自从智能手机普及之后就已经不再是小众爱好&#xff0c;使用手机拍摄记录生活几乎成了人们的日常。在巨量的需求下&#xff0c;美颜工具、美颜SDK已经被广泛应用于各大视频拍摄平台。虽然经常听到美颜SDK&#xff0c;但是大多数人并不了解它&#xff0c;下文小…...

Linux下C/C++ 网络扫描(主机扫描技术)

主机扫描是网络扫描的基础&#xff0c;通过对目标网络中主机IP地址的扫描&#xff0c;从一堆主机中扫描出存活的主机&#xff0c;然后以他们为目标进行后续的攻击。一般会借助于ICMP、TCP、UDP等协议的工作机制&#xff0c;检查打开的进程&#xff0c;开放的端口号等等。 主机…...

无法将“vue-cli-service”项识别为 cmdlet、函数、脚本文件或不是内部命令的原因和解决方案

经常有小伙伴问我说&#xff0c;为什么我们在开发vue项目的时候&#xff0c;需要在package.json的script对象中&#xff0c;去设置命令启动项目&#xff0c;而不是直接的通过"vue-cli-service serve"命令去把项目跑起来。带着这些疑问&#xff0c;小生在此总结了以下…...

逆流程 场景下 处理状态机变化的方案

背景&#xff1a; 针对某些业务场景下&#xff0c;存在逆流程。 比如场景的场景 正向流程如&#xff0c;发起某项申请->对某项申请进行审批。&#xff08;审批为通过/驳回&#xff09;。这样这个工作流程就算到最终态。 常见的状态机如&#xff0c; 申请未提交&#xff0…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...