文章目录
字典
如何定义字典
var m1 map[string]int //使用字面量创建
m2 := make(map[string]int) //容量使用默认值
m3 := make(map[int]interface{
},100) //使用内置make函数创建,指定容量为100
m4 := map[string]string{
"name":"james",
"age":"35",
}
- map声明时可以不指定容量,可以动态增长,但是若已知map容量为提高程序效率也可提前指明
- 不能使用不能比较的元素作为字典的key,例如数组,切片等
- value可以是任意类型的,如果使用interface{}作为value类型,那么就可以接受各种类型的值,只不过在具体使用的时候需要使用类型断言来判断类型
字典操作
字典插入元素
package main
import "fmt"
func main(){
m1 := make(map[string]string)
//var m1 map[string]string //使用此方式声明后运行会报错
//因为声明后并未初始化它,所以它的值是nil, 不指向任何内存地址
//需要通过make方法分配确定的内存地址。
m1["key1"] = "v1"
//m1["key1"] = "v2" //使用相同的key会覆盖
m1["key2"] = "v2"
m1["key3"] = "v3"
fmt.Println(m1["key1"]) //输出v1
fmt.Println(len(m1)) //输出3
}
判断键值对是否存在
有些情况下,不能确定键值对是否存在,或者当前value存储的是否就是空值,go语言中可以通过下面这种方式很简便的进行判断:
if value, ok := m1["key4"]; ok {
fmt.Println(value)
}
上面这段代码的作用就是如果当前字典中存在key为name的字符串则取出对应的value,并返回true,否则返回false。
遍历字典
for key,value := range m1{
fmt.Println(key+","+value)
}
删除元素
delete(m1, "key1")
将函数作为值存入字典中
func main() {
m := make(map[string]func(a, b int) int)
m["add"] = func(a, b int) int {
return a + b
}
m["multi"] = func(a, b int) int {
return a * b
}
fmt.Println(m["add"](3, 2))
fmt.Println(m["multi"](3, 2))
}
字符串
字符串定义
字符串是一种值类型,在创建字符串之后其值是不可变的。
在C语言中字符串是通过\0
来标识字符串的结束,而go语言中是通过长度来标识字符串是否结束的。
如果想要修改一个字符串的内容,可以将其转换为字节切片,再将其转换为字符串,但是也同样需要重新分配内存。
func main() {
s := "hello"
b := []byte(s)
b[0] = 'g'
s = string(b)
fmt.Println(s) //gello
}
如果字符串中包含中文就不能直接使用byte切片对其进行操作,go语言中可以通过这种方式:
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
s := "hello你好中国"
fmt.Println(len(s)) //17,每个中文3个字节
fmt.Println(utf8.RuneCountInString(s)) //9
b := []byte(s)
for i := 0; i < len(b); i++ {
fmt.Printf("%c", b[i])
} //输出 helloä½ å¥½ä¸å�½
fmt.Println()
r := []rune(s)
for i := 0; i < len(r); i++ {
fmt.Printf("%c", r[i])
} //hello你好中国
}
strings包
strings包提供了许多操作字符串的函数。在这里可以看到都包含哪些函数:https://golang.org/pkg/strings/
func main() {
var str string = "This is an example of a string"
//判断字符串是否以Th开头
fmt.Printf("%t\n", strings.HasPrefix(str, "Th"))
//判断字符串是否以aa结尾
fmt.Printf("%t\n", strings.HasSuffix(str, "aa"))
//判断字符串是否包含an子串
fmt.Printf("%t\n", strings.Contains(str, "an"))
}
strconv包
strconv包实现了基本数据类型与字符串之间的转换。在这里可以看到都包含哪些函数:https://golang.org/pkg/strconv/
i, err := strconv.Atoi("-42") //将字符串转为int类型
s := strconv.Itoa(-42) //将int类型转为字符串
若转换失败则返回对应的error值
字符串拼接
SPrintf
const numbers = 100
func BenchmarkSprintf(b *testing.B) {
b.ResetTimer()
for idx := 0; idx < b.N; idx++ {
var s string
for i := 0; i < numbers; i++ {
s = fmt.Sprintf("%v%v", s, i)
}
}
b.StopTimer()
}
动 词 | 功 能 |
---|---|
%v | 按值的本来值输出 |
%+v | 在 %v 基础上,对结构体字段名和值进行展开 |
%#v | 输出 Go 语言语法格式的值 |
%T | 输出 Go 语言语法格式的类型和值 |
%% | 输出 % 本体 |
%b | 整型以二进制方式显示 |
%o | 整型以八进制方式显示 |
%d | 整型以十进制方式显示 |
%x | 整型以十六进制方式显示 |
%X | 整型以十六进制、字母大写方式显示 |
%U | Unicode 字符 |
%f | 浮点数 |
%p | 指针,十六进制方式显示d |
+拼接
func BenchmarkStringAdd(b *testing.B) {
b.ResetTimer()
for idx := 0; idx < b.N; idx++ {
var s string
for i := 0; i < numbers; i++ {
s += strconv.Itoa(i)
}
}
b.StopTimer()
}
bytes.Buffer
func BenchmarkBytesBuf(b *testing.B) {
b.ResetTimer()
for idx := 0; idx < b.N; idx++ {
var buf bytes.Buffer
for i := 0; i < numbers; i++ {
buf.WriteString(strconv.Itoa(i))
}
_ = buf.String()
}
b.StopTimer()
}
strings.Builder拼接
func BenchmarkStringBuilder(b *testing.B) {
b.ResetTimer()
for idx := 0; idx < b.N; idx++ {
var builder strings.Builder
for i := 0; i < numbers; i++ {
builder.WriteString(strconv.Itoa(i))
}
_ = builder.String()
}
b.StopTimer()
}
对比
BenchmarkSprintf-8 68277 18431 ns/op
BenchmarkStringBuilder-8 1302448 922 ns/op
BenchmarkBytesBuf-8 884354 1264 ns/op
BenchmarkStringAdd-8 208486 5703 ns/op
可以看到通过strings.Builder拼接字符串是最高效的。