数据结构
# 数据结构
Owner: -QVQ-
# 字符串
不可改变类型
var city string = "我爱北京天安门"
city[0]='1'
错误,go的字符串不可变
支持转义字符:"妖怪\n放了我师父”
字符串拼接:str3 := "你好" + " 我是孙悟空”
# 字符串处理包
import strings
判断是不是以某个字符串开头,返回布尔值
res0 := strings.HasPrefix(str, "http://")
//判断是不是以某个字符串结尾
res3 := strings.HasSuffix(str, "http://")
//判断字符在字符串中首次出现的索引位置,没有返回-1
res5 := strings.Index(str, "o")
//返回字符最后一次出现的索引位置,没有返回-1
res7 := strings.LastIndex(str, "o")
//字符串替换
//trings.Replace("原字符串", "被替换的内容", "替换的内容", 替换次数)
(原字符串中有2个world,才能替换2次)
//求字符在字符串中出现的次数,不存在返回0次
countTime0 := strings.Count(str, "h")
//重复几次字符串
strings.Repeat("原字符串", 重复次数)
//字符串改大写 res14 := strings.ToUpper(str)
//字符串改小写 res15 := strings.ToLower(str)
//去除首尾的空格 res16 := strings.TrimSpace(str)
//去除首尾指定的字符,遍历l、d、e然后去除 res17 := strings.Trim(str, "ld")
//去除开头指定的字符 res18 := strings.TrimLeft(str, "he")
//去除结尾指定的字符,遍历d、l、r res19 := strings.TrimRight(str, "dlr")
//用指定的字符串将string类型的切片元素结合 str1 := []string{"hello", "world", "hello", "golang"} res20 := strings.Join(str1, "+")
# byte类型
表示单个的ascii字符,string单个取出是这个类型
# 数组
var arrayName [size]dataType
例子:var balance [10]float32
# 初始化数组
var numbers [5]int
//整数类型,初始值为0
初始化列表:var numbers = [10]int{1, 2, 3, 4, 5}
//没有赋值的会自动为0
注意数组的大小是类型的一部分,即不同大小的数组是不同的类型
根据元素自行推断数组长度
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 或 balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或
balance := []float32{1:2.0,3:7.0}
//自动推断大小为4
指定下标来初始化元素:
balance := [5]float32{1:2.0,3:7.0}
//没有指定的为0,注意这里的1和3是指的数组下标
for i, v := range nums{
}//i作为数组下标,v作为键值
2
# 多维数组
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
初始化二维数组
a := [3][4]int{
{0, 1, 2, 3} ,
{4, 5, 6, 7} ,
{8, 9, 10, 11}, //这里必须有,因为}不能单独一行
}//如果这个提上去,上面就可以不要逗号
2
3
4
5
创建各个维度元素数量不一致的多维数组
append()函数加入元素,不需要额外的包
// 创建空的二维数组
animals := [][]string{}
// 创建三个一维数组,各数组长度不同
row1 := []string{"fish", "shark", "eel"}
row2 := []string{"bird"}
row3 := []string{"lizard", "salamander"}
// 使用 append() 函数将一维数组添加到二维数组中
animals = append(animals, row1)
animals = append(animals, row2)
animals = append(animals, row3)
// 循环输出
for i := range animals {
fmt.Printf("Row: %v\n", i)
fmt.Println(animals[i])
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 向函数传递数组
void myFunction(param [10]int)
{
.
}
////////////////////////////
void myFunction(param []int, size int)
{//往往需要一个int来表示大小
.
}
2
3
4
5
6
7
8
9
# 指针
取值符&
fmt.Printf("变量的地址: %x**\n**", &a )
指针声明
var var_name *var-type
例:
var ip *int */* 指向整型*/ var fp *float32 */* 指向浮点型 */
var a int = 10
var ptr *b
b = &a
//直接输出b就是指针变量的值,也就是地址
//*b为指针指向的值
//使用方式同c
2
3
4
5
6
Go空指针,定义了没有分配到任何变量时,值为nil,指代空指针0
# 空间申请
以下两种等价
student := new(int)
student := &int{}
# 整型指针数组
var ptr [MAX]*int;
var ptr [MAX]*int;
for i = 0; i < MAX; i++ {
ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
}//需要循环一次赋值
2
3
4
5
注意数组本身并不是指针,可能是一个类之类的东西
指针的指针
var ptr **int
# 结构体
type Books struct {
title string //不用加var
author string
subject string
book_id int
}//定义
var a book = book{1,2}//使用
fmt.Println(a)//直接输出结构体,会顺序输出值
2
3
4
5
6
7
8
结构体.成员名
进行访问
结构体指针
var 变量名 *Books
struct_pointer.title
//同样用 . 访问结构体成员
# 切片
一种动态数组长度的数据结构,
声明:
var identifier []type
var slice1 []type = make([]type, len)
slice1 := make([]type, len)
len是切片的初始长度
可以指定容量:
make([]T, length, capacity)
切片初始化:
s :=[] int {1,2,3 }
将下标startIndex 到 endIndex-1的元素创建为一个新的切片,不填 endIndex 时将表示一直到arr的最后一个元素。
s := arr[startIndex:endIndex]
通过内置函数 make() 初始化切片s
s := make([]int,len,cap)
//,[]int 标识为其元素类型为 int 的切片:len表示长度,cap表示容量
**len(a)**获取切片长度
**cap(a)**获取切片容量
var a []int = make([]int, 3, 5)
//此时输出a为[0 0 0]
空切片(nil)未初始化时,都为nil
追加切片:
numbers = append(numbers, 0)
//追加空切片
numbers = append(numbers, 2, 3, 4)
//追加
删除
numbers = numbers[:len(numbers)-1]
复制:
copy(numbers1, numbers)
//拷贝numbers的内容到numbers1
# 范围Range
在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对
for key, value := range oldMap {
newMap[key] = value
}//其中key和value值可以省略,只读部分值
2
3
# map集合
无序的键值对的集合
可以遍历,只是返回的键值对的顺序不确定
获取map时,键不存在返回对应类型的零值
map是引用类型,map可以传递给函数,函数可以修改外层map的值
定义
/* 使用 make 函数 */
map_variable := make(map[KeyType]ValueType, initialCapacity)
//KeyType 是键的类型,
//ValueType 是值的类型,
//initialCapacity 是可选的参数,用于指定map的初始容量
// 当达到容量时,map会自动扩容
var m map[string]string /*创建集合 */
// 使用字面量创建 Map
m := map[string]int{
"apple": 1,
"banana": 2,
"orange": 3,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
增删改查
// 获取键值对
v1 := m["apple"]
v2, ok := m["pear"] // 如果键不存在,ok 的值为 false,v2 的值为该类型的零值
// 修改键值对
m["apple"] = 5
// 获取 Map 的长度
len := len(m)
// 遍历 Map
for k, v := range m {
fmt.Printf("key=%s, value=%d\n", k, v)
}
// 删除键值对
delete(m, "banana")
2
3
4
5
6
7
8
9
10
11
12
13
# Go语言接口
它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口
接口可以让我们将不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计
接口是隐式实现的,也就是说,如果一个类型实现了一个接口定义的所有方法,那么它就自动地实现了该接口
接口的定义:
/* 定义接口 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/* 方法实现*/
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
接口的使用:
package main
import (
"fmt"
)
//定义了一个接口Phone
type Phone interface {
call()//一个方法
}
//不同结构体类型
type NokiaPhone struct {
}
type IPhone struct {
}
//不同类型绑定到一组公共方法上,实现了多态
func (nokiaPhone NokiaPhone) call() {
fmt.Println("I am Nokia, I can call you!")
}
func (IPhone IPhone) call() {
fmt.Println("I am iPhone, I can call you!")
}
func main() {
var phone Phone
phone = new(NokiaPhone)
//等同于phone = NokiaPhone{}
phone.call()
phone = new(IPhone)
phone.call()
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
接口类型变量可以存储任何实现了该接口的类型的值
当定义了该类型的接口后,该类型均可使用该接口
# Go语言类型转换
# 数值类型转换
类型转换基本格式:type_name(expression)
var a int = 10
var b float64 = float64(a)
2
# 字符串类型转换
# 字符串转整型
package main
import (
"fmt"
"strconv"
)
str := "123"
num, err := strconv.Atoi(str)
if err != nil {
fmt.Println("转换错误:", err)
} else {
fmt.Printf("字符串 '%s' 转换为整数为:%d\n", str, num)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
num, _ = strconv.Atoi(str)
//这个函数返回两个值,第一个是转换后的整型值,第二个是可能发生的错误,可以用_来忽略这个值
# 整型转字符串
str := strconv.Itoa(123)
//”123“
# 将字符串转为浮点数
num, err := strconv.ParseFloat(str, 64)
# 将浮点数转换为字符串
str := strconv.FormatFloat(num, 'f', 2, 64)
# 接口类型转换
类型断言用于将接口类型转换为指定类型
value.(type)
或者 value.(T)
其中 value 是接口类型的变量,type 或 T 是要转换成的类型
如果类型断言成功,它将返回转换后的值和一个布尔值,表示转换是否成功
var i interface{} = "Hello, World"
str, ok := i.(string)//str接收转换后的值,ok用于检测转换是否成功
if ok {
fmt.Printf("'%s' is a string\n", str)
} else {
fmt.Println("conversion failed")
}
2
3
4
5
6
7
类型转换用于将一个接口类型的值转换为另一个接口类型
T 是目标接口类型,value 是要转换的值。
package main
import "fmt"
type Writer interface {
Write([]byte) (int, error)
}
type StringWriter struct {
str string
}
func (sw *StringWriter) Write(data []byte) (int, error) {
sw.str += string(data)
return len(data), nil
}
func main() {
var w Writer = &StringWriter{}//实例化一个结构体给接口类型变量w
//这里sw为 var sw *StringWriter
sw := w.(*StringWriter)// w 转换为 *StringWriter 类型给变量 sw
sw.str = "Hello, World"//
fmt.Println(sw.str)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 通用操作
func len(V Type) int
- 数组或数组指针:返回元素个数
- map和slice: 元素个数
- channel:通道中未读的元素个数
- 字符串:字节数,并非字符串的字符数
- 当V的值为nil值,len返回0
# 初始化
make只能用于slice、map和channel的初始化
new只用于内存分配
dp := make([]bool, len(s) + 1)