map数据类型

类比字典

声明/初始化

m:=map[string]int{
  "one":1,
  "two":2,
  "three":3
}

m1:=map[string]int{}
m1["one"]=1

m2:=make(map[string]int, 10)  // 这里的10 是 capacity
len(m2) // 0   

为什么map初始化没有len ?

length:一般初始化都会为‘零值’, 但是map是没有 ‘零值’, 字典/map的零值:就是:{}

不支持cap函数的访问!!

map的访问

  • key 不存在于map

    • 访问不存在的key,会自动返回初始化时候定义的‘零值

    • 如果本身设置的初始值就是‘零值’:??? 怎么判断key是否存在呢? go没有keyError,即不能通过nil判断key是否存在

m:=map[int]int
t.Log(m[1])  // 0
// 赋值 也为 0 值 如何判断?
m[2]=0
t.Log(m[2])  // 0

// go 对key是否存在key
if v,ok:m1[3];ok{
  // do sth
}else{
  // do sth
}

字典map的访问,返回的是双值,一个是v,表示本身的值,一个是status状态,bool类型,表示key是否存在

map遍历

for
m:=map[string]int{
  "one":1,
  "two":2,
  "three":3
}
for key,v:range m{
  // do sth
}

map与工厂模式

  • map的value可以是一个方法(或者说object)
  • 与go的Dock type 接口方式一起,可以方便的实现单一方法对象的工厂模式

单元测试示例:

package map_ext

import "testing"

func TestMapWithFunValue(t testing.T){
  m:=map[int]func(op int)int{}    // 定义value是func。func参数op和返回值都是int
  // 添加元素
  m[1]=func(op int) int { return op }
  m[2]=func(op int) int { return op*op }
  m[3]=func(op int) int { return op*op*op} 
  t.Log(m[1](2),m[2](2),m[3](2))  // 2  4. 8
}
集合Set:不存在与go的数据结构

go的内置集合中没有set的实现,可以使用map[type]bool的方式实现

  • 元素的唯一性
  • 基本操作:
    • 添加元素
    • 判断元素是否存在
    • 删除元素
    • 元素个数

实现Set

func TestMapForSet(t testing.T) {
  myset:=map[int]bool{}
  // 添加元素
  myset[1]=true
  n:=1
  // 判断元素是否存在
  if myset[n]{
    // do sth
  }else{
     // do sth
  }
  s:=3
  if myset[s]{
    // do sth
  }else{
    // do sth
  }
  
  // 输出集合set的个数
  len(myset)
  
  // 删除元素
  delete(myset,n)
}
golang-string类型
  • string是数据类型,不是引用或者指针类型
  • string是只读byte slice,len函数可以测量出它所包含的byte数–差异
  • string的byte数组可以存放任何数据
func TestString (t testing.T){
    var s string
    t.Log(s)  // 初始化默认为 ''
    
    // 赋值
    s = 'hello'
    t.Log(len(s))  // 5   5 个英文字符
    
    s = "\xE4\xB8\xA5"
    t.Log(s) // 输出 ‘严’  s是  严 的中文的十六进制
    t.Log(len(s)) // 3   中文的长度 实际上是 s的byte组成的长度  \xE4\xB8\xA5
    
    // 任意赋值
    s = "\xE4\xB8\xBB\xA5"
    t.Log(s)  // 输出  彳?   乱码的字
    t.Log(len(s))  // 4
    
    s = "hello"
    // s[1] = "3"  // 报错  string是一个不可变的byte 切片
}

unicode和utf8

  • unicode是一种字符集 又叫 code point
  • UTF8是unicode的存储实现(转换为字节系列的规则)

示例:

func TestUnicode (t testing.T) {
    var s string
    s = "中"
    t.Log(len(s))  // 3  是byte数
    
    
    c := []rune(s)
    t.Log(len(c))  // 1   所以其实就是 中 这个汉字的长度
    // %x  表示输出十六进制
    t.Logf("中 unicode %x", c[0])   // 中 unicode 4e2d 
    t.Logf("中 UTF8 %x", s) // 中 UTF8  e4b8ad 
    
}

编码与存储

字符
unicode0x4E2D
UTF-80xE4B8AD
string/[]byte[0xE4,0xB8,0xAD]

常用的字符串函数

遍历一个字符串

for
s:="中华人民共和国"
for _,v:=range s {
    t.Logf("%[1]c %[1]d", v) // [1] 表示 第一个参数   以%c   以%d 十进制 格式化  或者%x 输出十六进制
}

相关函数

strings
import "strings"

func TestStringFunc (t testing.T) {
    s:="A,B,C,D"
    // 分割
    parts:=strings.Split(s, ",")
    for _,v:=range parts {
        t.Log(v)
    }
    // 连接 join
    t.Log(strings.Join(parts, "-"))  // "A-B-C-D"
    
}
strconv
import "strconv"

func TestConvfunc (t testing.T) {
    s:=strconv.Itoa(10)  // I 表示 integer    a表示ascii
    t.Log("str"+s)  // str10
    
    // t.Log(10 + strconv.Atoi("10"))  // 20?? 不 这样是不对的。 因为 字符串转 整数  必须是整形字符,因此要判断
    // go 的设计上已经考虑到了
    if i,err:=strconv.Atoi("10");err==nil{
        t.Log(10+i)  // 20
    }
}