每种语言在实现数据结构有些许不同。go 是如何实现的呢?

1. 数组 Array

  • go 中数组是相同的元素组成的集合,计算机会为数组分配一段连续的内存来保存元素,可以利用索引快速访问元素。
  • go 中数组用两个维度来描述:元素类型 和 元素个数。元素类型相同,大小不同的数组在 go 中被认为是不同的数据类型。只有两者完全相同才是相同的类型。
  • 数组在舒适化之后大小就无法改变了。
  • 数组的长度是固定的,数据越界是严重的错误,但在编译阶段 go 自动检查越界问题。
package main

import "fmt"

func main() {
x := [7]int{1, 2}
x[3] = 4 // [1 2 0 4 0 0 0] // x[8] = 8 越界无法通过编译 a := [3]int{1, 2, 3}
b := [...]int{1, 2, 3} // 类型推导 // x 和 a,b 是两种不同的数据类型
// 编译器会把 b数组 翻译成 a 这种类型。
fmt.Printf("%T\n", x)
fmt.Printf("%T\n", a)
fmt.Printf("%T\n", b) fmt.Println(x)
fmt.Println(a)
fmt.Println(b)
} E:>go run main.go
[7]int
[3]int
[3]int
[1 2 0 4 0 0 0]
[1 2 3]
[1 2 3]

2. 切片 Slice

由于 数组长度固定, 无法直接扩容追加元素,所以在写 go 代码时,数组用的并不多。

  • 切片是动态的数组,其长度不固定,可以追加元素,容量不足是会自定扩容。
  • 切片是引用类型,指针指向一个底层数组。切片除了 元素类型,长度,还有 容量的概念。可以将切片理解为一块连续的内存空间加上长度与容量的标识。
  • 切片可以修改长度和容量。但是当切片指向的底层数组长度不足时会触发数组扩容,copy 数据到一个更长的数组。而切片指针指向一个新的数组。但上层看来切片并没有变化,

    使用切片时,不必担心底层数组的变化。
  • 使用下标初始化切片不会复制原数组或切片中的数据,指挥创建一个指向原数组的切片结构体,所以修改新切片的数据也会修改原切片。
  • 字面量生成的切片大多数在编译阶段完成,make 关键字创建的切片大多数在运行时完成。

通常有三种方式获取一个切片:

  1. 从一个数组
  2. 使用字面量初始化切片
  3. make 关键字创建切片

也可以从一个切片获取切片(切片再切片)

package main

import "fmt"

func main () {
array := [5]string{"a","b","c","d","e"}
fmt.Printf("array Type is :%T; value is %s\n",array,array) // 1. 从数组获取一个切片
s1 := array[0:3]
fmt.Printf("s1 Type is :%T; value is %s\n",s1,s1)
s11 := s1[0:2] // 切片再切片
fmt.Printf("s11 Type is :%T; value is %s\n",s11,s11) s1[0] = "aa" // 切片再切片时,底层切片修改的元素的值, 新切片的值也会随着改变
s11[1] = "bb" // 切片再切片时,新切片修改的元素的值, 底层切片的值也会随着改变
fmt.Printf("### s1 Type is :%T; value is %s\n",s1,s1)
fmt.Printf("### s11 Type is :%T; value is %s\n",s11,s11) // 2. 从字面量初始化
s2 := []string{"x","y","z","n"}
fmt.Printf("s2 Type is :%T; value is %s\n",s2,s2)
s22 := s2[0:2]
fmt.Printf("s22 Type is :%T; value is %s\n",s22,s22) s2[0] = "xx" // 切片再切片时,底层切片修改的元素的值, 新切片的值也会随着改变
fmt.Printf("### s2 Type is :%T; value is %s\n",s2,s2)
fmt.Printf("### s22 Type is :%T; value is %s\n",s22,s22) // 3. make 函数初始化
s3 := make([]int,5,10)
s3[1] = 2
fmt.Printf("s3 Type is :%T; value is %d\n",s3,s3) } E:>go run slice.go
array Type is :[5]string; value is [a b c d e]
s1 Type is :[]string; value is [a b c]
s11 Type is :[]string; value is [a b]
### s1 Type is :[]string; value is [aa bb c]
### s11 Type is :[]string; value is [aa bb]
s2 Type is :[]string; value is [x y z n]
s22 Type is :[]string; value is [x y]
### s2 Type is :[]string; value is [xx y z n]
### s22 Type is :[]string; value is [xx y]
s3 Type is :[]int; value is [0 2 0 0 0]

切片扩容:

  • len(slice) < 1024 , * 2
  • len(slice) > 1024, * 25%

切片 append 和 copy

    s5 := []int{1,3,5}
//s6 := make([]int,10,10)
s6 := []int{2,4,6,8,10}
//s5 = append(s5,7)
copy(s6,s5)
fmt.Println(s5,s6) // [1 3 5] [1 3 5 8 10] 复制整个大切片,消耗内存较多,应该避免此类操作影响程序的性能。

3. 哈希表

哈希表是go语言中另一种集合类型,数组用于标识元素的序列,而哈希表表示的是键值对之间的映射关系。

哈希函数和解决哈希冲突是实现一个性能优异的哈希表的关键:理想的情况下,哈希函数应该能将不同的键映射到不同的索引上,这就要求哈希函数的输出范围要大于输入范围,但是由于

键的数量会远远大于映射的范围,所以在实际使用时这个效果不可能实现。比较实际的方式是让哈希函数的结果尽可能的均匀分布,然后通过工程手段解决哈希冲突的问题。不均匀的哈希

的哈希函数读写性能可能会达到 O(n)。在完美的哈希函数,当键的数量足够多是也会产生冲突。开放寻址法和拉链法是解决哈希冲突常用的两种方式。大多数编程语言和数据库通常会选择

拉链发解决冲突,开放寻址法解决冲突底层用的依然数组,而拉链法用 数组+链表 实现了一个 哈希桶,相当于一个二位数组,冲突时放到桶里,而查询时只需要遍历这个链表(桶),但

通常链表的长度控制在4以内,否则性能不太高。

有两种方式得到一个 map:

  • 字面量
  • make 函数
package main

import (
"fmt"
) func main() {
// 1. 字面量生成map
m1 := map[int]string{
1: "a",
2: "b",
3: "c",
} // make 函数生成 map
m2 := make(map[int]string)
m2[1] = "a"
m2[2] = "b"
m2[3] = "c" fmt.Printf("%#v\n",m1)
//fmt.Printf("%#v\n",m2) // 遍历 map
for i:=1;i<=len(m2);i++{
if m2[i] == "a"{
m2[i] = "aa"
}
fmt.Println(i,m2[i])
} // 删除 元素
delete(m1,1)
fmt.Printf("%#v\n",m1) // v,ok 判断 key 是否存在
v,ok := m1[1]
if !ok {
fmt.Println("key is not exists")
} else {
println(v)
} }

4. 字符串

  • 字符串是字符组成的数组
  • string 和 []byte 类型可以互相转换。
  • go 语言中 '' 与 “ ” 是有区别的 。支持 + 号 拼接字符串。
  • 返单引号声明的 string 变量, 在 使用json 字符串时很方便
package main

import "fmt"

func main() {
name := "Hello world"
nameN := []byte(name) fmt.Println(nameN) hobby := `` }

Golang 数据结构的更多相关文章

  1. golang数据结构之总结

    golang语言的一些数据结构实现,包括: 队列(单队列.循环队列) 链表(单链表.双链表.循环链表(解决约瑟夫环问题)) 栈(实现加减乘除计算) 递归之迷宫问题 哈希表(员工管理系统) 树(三种遍历 ...

  2. golang数据结构和算法之BinarySearch二分查找法

    基础语法差不多了, 就需要系统的撸一下数据结构和算法了. 没找到合适的书, 就参考github项目: https://github.com/floyernick/Data-Structures-and ...

  3. golang数据结构之队列

    队列可以用数组或链表实现,遵从先入先出. 目录结构: 在main中调用queue包中的属性和方法,如何调用参考另一篇文章: https://www.cnblogs.com/xiximayou/p/12 ...

  4. golang数据结构之循环链表

    循环链表还是挺有难度的: 向链表中插入第一条数据的时候如何进行初始化. 删除循环链表中的数据时要考虑多种情况. 详情在代码中一一说明. 目录结构如下: circleLink.go package li ...

  5. golang数据结构之树的三种遍历方式

    tree.go package tree import ( "fmt" ) type TreeNode struct { ID int Val int Left *TreeNode ...

  6. golang数据结构之散哈希表(Hash)

    hash.go package hash import ( "fmt" ) type Emp struct { ID int Name string Next *Emp } //第 ...

  7. golang数据结构之递归解决迷宫问题

    简单来说:递归就是函数/方法自己调用自己,只是每次传入不同的变量. 递归可以解决各种数学问题:n皇后问题.阶乘问题.汉诺塔.迷宫问题.球和篮子问题等等: maze.go package maze im ...

  8. golang数据结构之利用栈求计算表达式(加减乘除)

    例如:3+2*6-2 先定义两个栈,一个为数值栈,一个为运算符栈: stack.go package stack import ( "errors" "fmt" ...

  9. golang数据结构之栈

    stack.go package stack import ( "errors" "fmt" ) type Stack struct { MaxTop int ...

随机推荐

  1. 按照递推的思想求解next[]数组

    按照递推的思想求解next[]数组 根据定义next[0]=-1,假设next[j]=k, 即P[0...k-1]==P[j-k,j-1] 若P[j]P[k],则有P[0..k]P[j-k,j],很显 ...

  2. 1Appium Desktop 的简单应用

    由于Appium Desktop出来了,所以使用appium要比以前简单许多,现在根据以前的文章针对Appium Desktop做下修改更新 之前文章链接:https://testerhome.com ...

  3. 【ybtoj】二分算法例题

    [基础算法]第三章 二分算法 例一 数列分段 题目描述 对于给定的一个长度为N的正整数数列A,现在将其分成M段,并要求每段连续,且每段和的最大值最小. 输入格式 第1行包含两个正整数N,M. 第2行包 ...

  4. io流复习+代码演示

    前置知识: 序列化和反序列化 1.序列化就是在保存数据时, 保存数据的值和数据类型 2.反序列化就是在恢复数据时, 恢复数据的值和数据类型 3.需要让某个对象支持序列化机制,则必须让其类是可序列化的, ...

  5. 关于NSMutableAttributedString进行富文本 UILabel 的制作

    //1.初始化与其他无异 NSMutableAttributedString *AttributedStr2 = [[NSMutableAttributedString alloc]initWithS ...

  6. 关于WebStorm 破解

    建议资金宽裕,支持正版 2017.2.27更新 选择"license server" 输入:http://idea.imsxm.com/ 2016.2.2 版本的破解方式: 安装以 ...

  7. 微服务从代码到k8s部署应有尽有系列(八、各种队列)

    我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...

  8. RFC2899广播帧转发测试——网络测试仪实操

    一.简介 RFC 2889为LAN交换设备的基准测试提供了方法学,它将RFC 2544中为网络互联设备基准测试所定义的方法学扩展到了交换设备,提供了交换机转发性能(Forwarding Perform ...

  9. 国内主流大数据厂商太多不知道怎么选?Smartbi满足你的需求

    ​目前的BI市场上有很多大数据的厂商,这也让许多客户眼花缭乱,不知如何下手.比如国内的亿信华辰跟国外的Tableau,QLK, PowerBI 都有非常多便于分析的可视化工具,但是在数据处理分析的功能 ...

  10. Linux:査看文件的详细信息

    Linux中stat是査看文件详细信息的命令. 1.命令格式: stat [选项] 文件名/目录名 2.选项: -f:査看文件所在文件系统信息,而不是査看文件信息. 3. 案例 案例1:査看文件的详细 ...