类比字典
声明/初始化
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
}
编码与存储
字符 | 中 |
---|---|
unicode | 0x4E2D |
UTF-8 | 0xE4B8AD |
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
}
}