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

公司企业网站建设的建站流程解析html网站设计

公司企业网站建设的建站流程解析,html网站设计,无区域公司怎么注册,thinkphp商城源码#x1f525; 个人主页#xff1a;空白诗 #x1f525; 热门专栏#xff1a;【Go语言精进之路】 文章目录 引言一、什么是map1.1 map的基本概念与特性1.2 map的初始化与零值问题1.3 map作为引用类型的行为 二、map的基本操作2.1 插入数据2.2 获取数据个数2.3 查找和数据读取… 个人主页空白诗 热门专栏【Go语言精进之路】 文章目录 引言一、什么是map1.1 map的基本概念与特性1.2 map的初始化与零值问题1.3 map作为引用类型的行为 二、map的基本操作2.1 插入数据2.2 获取数据个数2.3 查找和数据读取2.4 删除数据2.5 遍历数据 三、map的内部实现3.1 初始状态3.2 map扩容3.3 map并发 四、尽量使用cap参数创建map五、总结 引言 在Go语言中map 是一种无序的键值对集合它以其高效的查找、插入和删除操作而闻名。了解 map 的基本概念、特性和内部实现机制对于编写高效且稳定的Go代码至关重要。本文将深入探讨 map 的各个方面包括其初始化、基本操作、内部实现细节并讨论为何在创建 map 时应尽量使用带有容量提示参数的做法。 一、什么是map 1.1 map的基本概念与特性 map是Go语言中的一种内建引用类型它表示一组无序的键值对集合。每个键值对用冒号“:”分隔其中键key是唯一的用于标识对应的值value。map允许我们根据特定的键快速检索、更新或删除对应的值。 在Go语言中map对值value的数据类型没有特定限制它可以是任意类型包括基本类型、结构体、自定义类型等。但是键key的类型有严格要求key的类型必须可以通过“”和“!”操作符进行比较这意味着键的类型需要是可比较的。因此像函数、map和切片这样不可比较的类型不能作为map的键。 1.2 map的初始化与零值问题 需要注意的是map类型不支持“零值可用”也就是说未显式初始化的map变量其默认值为nil。尝试对nil的map变量进行操作将会导致运行时错误panic。例如 var m map[string]int // 此时m的值为nil // 下面的操作将会导致运行时panic因为m未被初始化 m[key] 1 // panic: assignment to entry in nil map为了避免这种情况我们需要在使用map之前对其进行初始化。可以通过以下两种方式之一来初始化map 使用make函数初始化 m : make(map[string]int) m[key] 1 // 现在这是安全的因为m已经被初始化使用字面量初始化 m : map[string]int{key: 1} // 或者 m : map[string]int{} m[key] 1 // 同样是安全的因为m已经被初始化初始化后的map可以被安全地用于存储和检索键值对而不会导致运行时错误。在Go程序中map是非常有用的数据结构特别适用于需要根据键快速查找、添加或删除相应值的场景。 1.3 map作为引用类型的行为 和切片一样map也是引用类型。这意味着当你将一个map类型的变量传递给函数时实际上传递的是指向底层数据结构的指针而不是整个数据结构的拷贝。因此将map类型变量作为函数参数传入不会有很大的性能消耗。 此外由于在函数内部和外部引用的是同一个底层数据结构所以在函数内部对map变量的修改如添加、删除键值对或更新值在函数外部也是可见的。这种特性使得map在需要在多个函数或方法间共享和修改数据时非常有用。 以下是一个示例展示了在函数内部修改map并在函数外部观察到这些修改 package mainimport fmtfunc modifyMap(m map[string]int) {// 在函数内部修改mapm[apple] 5m[banana] 10 }func main() {// 初始化一个mapfruitMap : make(map[string]int)// 调用函数传入map作为参数modifyMap(fruitMap)// 打印修改后的map可以看到在modifyMap函数中所做的修改fmt.Println(fruitMap) // 输出: map[apple:5 banana:10] }在这个例子中modifyMap函数接收一个map作为参数并在函数内部添加了两个键值对。当函数执行完毕后main函数中的fruitMap已经被修改反映了modifyMap函数中所做的更改。这是因为map是引用类型modifyMap接收的是fruitMap的引用因此对它的任何修改都会反映在原始map上。 二、map的基本操作 2.1 插入数据 当面对一个非nil的map类型变量时我们可以向其中插入符合map类型定义的任意键值对。值得注意的是如果试图插入的键key已经存在于map中那么新的值将会覆盖旧的值。Go运行时会管理map内部的内存因此除非系统内存耗尽否则我们不必担心向map中插入大量数据。 m : make(map[string]int) m[apple] 5 // 插入键值对 apple: 5 m[apple] 7 // 更新键 apple 的值为 7旧值5被覆盖 m[banana] 10 // 插入键值对 banana: 10在上述代码中我们首先创建了一个从string类型到int类型的map。然后我们插入了键值对apple: 5。紧接着我们尝试再次插入键apple但这次赋予它一个新的值7。由于这个键已经存在于map中因此旧的值5会被新的值7覆盖。最后我们插入了一个新的键值对banana: 10。 这种覆盖行为是map的一个重要特性它允许我们根据需要更新存储在map中的值。在实际编程中这一特性非常有用比如当我们需要根据某些条件动态改变值时。 2.2 获取数据个数 要获取map中数据的个数可以使用内置的len()函数。 count : len(m) fmt.Println(Number of items in map:, count) // 输出map中的元素个数len(m)返回m中当前存储的键值对数量。 2.3 查找和数据读取 可以根据键来查找和读取map中的数据。如果键不存在则返回该类型的零值。 value, exists : m[apple] // 查找键为apple的值并检查键是否存在 if exists {fmt.Println(The value of apple is:, value) } else {fmt.Println(apple does not exist in the map.) }使用value, exists : m[key]的格式可以同时获取键对应的值和该键是否存在。如果键存在exists为true并且value为该键对应的值如果键不存在exists为falsevalue为该类型的零值。 2.4 删除数据 要从map中删除一个键值对可以使用delete()函数。 delete(m, banana) // 删除键为banana的键值对delete(m, key)函数会从m中删除与key关联的键值对。如果key不存在则delete什么也不做。 2.5 遍历数据 可以使用range关键字来遍历map中的所有键值对。 package mainimport fmtfunc main() {m : map[int]int{1: 11, 2: 12, 3: 13,}fmt.Printf({ )for key, value : range m {fmt.Printf(key: %d, value: %d , key, value)}fmt.Printf( }\n) }range m会迭代m中的所有键值对每次迭代都会返回当前的键和值。在上面的循环中key和value分别被赋值为当前迭代的键和值然后打印出来。 上面的输出结果非常理想给我们的表象是迭代器按照map中的元素插入次序逐一遍历。那让我们再多遍历几次这个map package mainimport fmtfunc doIteration(m map[int]int) {fmt.Printf({ )for key, value : range m {fmt.Printf(key: %d, value: %d , key, value)}fmt.Printf( }\n) }func main() {m : map[int]int{1: 11,2: 12,3: 13,}for i : 0; i 3; i {doIteration(m)} }我们看见对同一map进行多次遍历遍历的元素次序并不相同。这是因为Go运行时在初始化map迭代器时对起始位置做了随机处理。因此千万不要依赖遍历map所得到的元素次序。 三、map的内部实现 和切片相比map类型的内部实现要复杂得多。Go运行时使用一张哈希表来实现抽象的map类型运行时实现了map操作的所有功能包括查找、插入、删除、遍历等。本文这里只做一些简单的介绍。 3.1 初始状态 在Go语言中当一个map被初始化时它会分配一个较小的内存空间来存储键值对数据。这个初始的内存空间包含一定数量的桶buckets每个桶能够存储一个或多个键值对。初始状态下这些桶都是空的。 map的初始化可以通过字面量、make函数或者直接使用map类型进行。例如 // 使用字面量初始化 m1 : map[string]int{apple: 5, banana: 10}// 使用make函数初始化 m2 : make(map[string]int)// 直接声明map类型变量需要后续进行初始化 var m3 map[string]int m3 make(map[string]int)在初始化时map会预留一定的空间以准备存储键值对但这个初始空间相对较小。 3.2 map扩容 当map中的元素数量增加负载因子已存储的键值对数量与桶的数量的比例也会随之增加。当负载因子超过某个预定的阈值时map会进行扩容以保证性能。 扩容过程中map会创建一个更大的桶数组并且重新计算所有现有键值对的哈希值将它们重新分布到新的桶数组中。这个重新哈希和分布的过程是为了确保键值对能够更均匀地分散在新的桶中从而减少哈希冲突并提高查找效率。 扩容是一个相对昂贵的操作因为它涉及到内存分配和大量数据的迁移。因此在实际使用中如果可能的话最好提前预估map的大小并一次性分配足够的空间。 3.3 map并发 Go语言的map类型并不是并发安全的。这意味着如果多个goroutine同时对一个map进行读写操作就可能导致数据竞争data race和不可预知的行为。 为了在并发环境中安全地使用map有几种常见的解决方案 使用互斥锁Mutex通过使用sync.Mutex或sync.RWMutex来同步对map的访问。在每次读写map之前先获取锁操作完成后再释放锁。 使用sync.MapGo语言标准库提供了一个并发安全的map实现即sync.Map。它内部使用了分段锁和其他优化技术来提供高效的并发访问。 通道Channel另一种方法是使用Go的通道来序列化对map的访问。通过将所有对map的操作都通过一个或多个通道来进行可以确保在同一时间只有一个goroutine能够访问map。 在实际应用中选择哪种并发控制方法取决于具体的使用场景和性能要求。对于简单的用例使用互斥锁可能就足够了而在需要高并发性能的场景中sync.Map可能更为合适。 四、尽量使用cap参数创建map 由于扩容是一个相对昂贵的操作因为它涉及到内存分配和大量数据的迁移因此如果可以的话我们最好对map使用规模做出粗略的估算并使用cap参数对map实例进行初始化。 当你创建一个 map 而不指定容量时Go 会自动为你分配一个初始的、未指定的容量。这个容量足以满足初始需求并且随着 map 中元素的增加Go 的运行时会自动管理其内部结构的大小调整以容纳更多的元素。这是最常见也是最简单的初始化方式。 m : make(map[string]int)如果你在创建 map 时明确指定了 cap 参数你是在给 Go 提供一个关于你期望 map 最终可能包含多少个键值对的提示。这有助于减少 map 在增长过程中需要重新分配内存的次数从而提高效率尤其是在你知道 map 大致会有多大时。但请注意指定的 cap 是一个提示而不是严格的限制map 的实际容量可能会略高于指定的值且 map 仍然可以在达到这个预设容量后继续增长。 m : make(map[string]int, 100)优缺点分析 不使用 cap简化初始化过程让Go自动管理容量适用于大多数情况特别是当你不确定map最终大小时。使用 cap通过预先估计map的大小可以略微优化性能减少动态扩容的次数适合于明确知道或能估算map容量的场景。 选择是否使用 cap 主要取决于你对map最终规模的了解程度和对性能的特定需求。在不需要精确控制初始容量的情况下省略 cap 是一个简洁且有效的方法。然而如果你正处理大量数据且关心性能优化明智地设定初始容量可以带来益处。 下面对两种初始化方式的性能进行对比 package mainimport testingconst mapSize 10000func BenchmarkMapInitWithoutCap(b *testing.B) {for i : 0; i b.N; i {m : make(map[int]int)for i : 0; i mapSize; i {m[i] i}} } func BenchmarkMapInitWithCap(b *testing.B) {for i : 0; i b.N; i {m : make(map[int]int, mapSize)for i : 0; i mapSize; i {m[i] i}} }BenchmarkMapInitWithoutCap函数执行以下操作 它使用一个循环该循环将运行b.N次其中b.N是testing.B提供的表示基准测试应该运行的次数。这是为了确保我们获得足够的数据点来平均性能测试结果从而获得更准确的数据。 在每次循环中它创建一个新的map没有指定初始容量make(map[int]int)。 然后它向这个map中插入mapSize即10000个键值对其中键和值都是循环变量i。 这个基准测试的目的是测量在不指定初始容量的情况下初始化并填充一个map的性能。 执行结果如下 BenchmarkMapInitWithCap函数与BenchmarkMapInitWithoutCap非常相似但有一个关键区别 在创建map时它使用make(map[int]int, mapSize)来指定一个初始容量提示这个容量提示等于将要插入的键值对的数量即10000。 这个基准测试的目的是测量在指定了与将要插入的键值对数量相等的初始容量提示的情况下初始化并填充一个map的性能。 下面是执行结果 可以看出使用cap参数的map实例的平均写性能是不使用cap参数的2倍。 五、总结 本文通过详细阐述了Go语言中 map 的基本概念、特性及其作为引用类型的行为介绍了 map 的基本操作如插入、获取数据个数、查找、删除和遍历数据等。同时深入剖析了 map 的内部实现包括其初始状态、扩容机制以及并发问题。最后本文强调了在使用 map 时为了提高性能和减少内存重新分配的次数应尽量在创建时提供合理的容量提示参数。通过全面理解 map 的工作原理和最佳实践开发者可以更加有效地利用这一强大的数据结构来优化程序性能。
http://www.w-s-a.com/news/47732/

相关文章:

  • 网站建设 目的seo网站关键词排名快速
  • 什么叫做响应式网站自媒体全平台发布
  • 企业网站 案例哪里需要人做钓鱼网站
  • 厚街东莞网站建设网站开发者调试模式
  • 网站推广营销联系方式wordpress adminlte
  • 哪些网站可以做文字链广告卖水果网站建设的策划书
  • 雕刻业务网站怎么做企业qq官网
  • 新华书店的做的数字阅读网站wordpress编辑器格式
  • jq做6个网站做什么好广西临桂建设局网站
  • 网站新闻图片尺寸南京网站设计公司
  • 重庆seo建站网站服务器 安全
  • 咸宁做网站的公司桂林网站建设兼职
  • 教做网站网站开发行业分析
  • 忻州网站建设培训友情链接交换形式有哪些
  • 佛山做外贸网站渠道外贸常用网站
  • 文章收录网站网站及新媒体建设办法
  • 招聘网站排行榜2021找建网站公司
  • 网站建设制作宝塔面板活动宣传推广的形式有哪些
  • 掉关键词网站敏捷软件开发流程
  • 微信小程序格泰网站建设新闻采编与制作专业简历
  • 电子商城建设网站海伦网站建设
  • 南充能够建设网站的公司有专门做设计的一个网站
  • 免费域名申请个人网站阿里巴巴运营的工作内容
  • 怎么建自己的手机网站保定电子商务网站建设
  • 系部网站建设中期检查表创建网站的公司
  • 西宁网站建设优化重庆企业的网站建设
  • 贝壳企业网站管理系统徽与章网站建设宗旨
  • 郑州网站模板动漫设计与制作设计课程
  • 在线制作网站的工具岳阳网站设计改版
  • 网站建设需要汇报哪些内容前端开发的工作内容