golang 入门(二) 常用数据结构slice切片
原创
©著作权归作者所有:来自51CTO博客作者hellowgw的原创作品,请联系作者获取转载授权,否则将追究法律责任
python常用的数据结构就是list。在golang中相对应的是slice(切片)。切片属性与python的list非常类似,用来存储一个数据序列。长度不限制。
先用python举例,创建一个list,然后向list中插入10个整数。由于python是弱类型语言,所以list里面什么数据格式都能塞进去。追加了int以后再追加string也没问题。
# 创建一个空的list
mylist = []
mystring_list = ['a', 'b', 'c']
#构造一个for循环,并向list里面追加10个整数数字
for i in range(1, 11):
mylist.append(i)
# 向mylist列表中追加字符串
for s in mystring_list:
mylist.append(s)
print(mylist)
/code/venv/bin/python test.py
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'a', 'b', 'c']
Process finished with exit code 0
但是golang是强类型语言,使用数据结构前要先进行明确的类型声明。即要< 明确告知 >golang解释器,这个序列里面存储数据类型是什么(int or string),这样就不能混着用了
package main
import "fmt"
func main() {
// 使用make初始化一个长度为0的slice切片,注意[]后面跟着的int就是声明slice中的数据类型只能是整数
myint_slice := make([]int, 0)
// 构造一个for循环,插入10个整型数字
for i := 1; i <= 10; i++ {
// 追加整数数字
myint_slice = append(myint_slice, i)
}
fmt.Println(myint_slice)
}
% go run main.go
[1 2 3 4 5 6 7 8 9 10]
尝试向myint_slice中插入string
package main
import "fmt"
func main() {
// 使用make初始化一个长度为0的slice切片,注意[]后面跟着的int就是声明slice中的数据类型只能是整数
myint_slice := make([]int, 0)
// 构造一个for循环,插入10个整型数字
for i := 0; i <= 10; i++ {
// 追加整数数字
myint_slice = append(myint_slice, i)
}
// 创建一个由内容的slice,字符串必须是双引号
mystring_slice := []string{"a", "b", "c"}
// 使用range 构造一个键值循环取货string类型slice的value,尝试向int类型slice中追加
for _, value := range mystring_slice {
myint_slice = append(myint_slice, value)
}
fmt.Println(myint_slice)
}
错误提示非常明显
% go run main.go
# command-line-arguments
./main.go:17:23: cannot use value (type string) as type int in append
其他的操作方法如:根据索引获取数据、判断slice长度等操作,基本都与Python差不多。不过slice没有list中类似pop的操作来删除元素。
package main
import "fmt"
func main() {
myintSlice := make([]int, 0)
for i := 1; i <= 10; i++ {
myintSlice = append(myintSlice, i)
}
fmt.Println(myintSlice)
fmt.Println(len(myintSlice))
fmt.Println(myintSlice[0])
fmt.Println(myintSlice[0:3])
}
% go run main.go
[1 2 3 4 5 6 7 8 9 10]
10
1
[1 2 3]
判断某一个元素是否包含在list 或 slice中
python实现相对简洁,通过if语句就可以实现
mylist = []
for i in range(1, 11):
mylist.append(i)
if 5 in mylist:
print('hahaha')
golang就没有这种语法糖,老老实实地slice中数据的值,先for出来再比对
package main
import "fmt"
func main() {
myintSlice := make([]int, 0)
for i := 1; i <= 10; i++ {
myintSlice = append(myintSlice, i)
}
for _, x := range myintSlice {
if x == 5 {
fmt.Println("hahaha")
}
}
}
类似的场景,删除list或slice中的指定元素
python实现
mylist = []
for i in range(1, 11):
mylist.append(i)
mylist.remove(5)
print(mylist)
python test.py
[1, 2, 3, 4, 6, 7, 8, 9, 10]
golang依旧需要老老实实的通过for循环来解决
package main
import "fmt"
func main() {
myintSlice := make([]int, 0)
// 新建一个空的slice用于存储结果
myintSliceNew := make([]int, 0)
for i := 1; i <= 10; i++ {
myintSlice = append(myintSlice, i)
}
for _, x := range myintSlice {
if x == 5 {
// 什么都不写,等同于python中的pass
} else {
myintSliceNew = append(myintSliceNew, x)
}
}
// 再赋值回原来的slice
myintSlice = myintSliceNew
fmt.Println(myintSlice)
}
% go run main.go
[1 2 3 4 6 7 8 9 10]
总结:
- 就基础语法来说,python确实简洁。其实类似于list.remove() 这种方法,python在底层实现的逻辑与golang也一样。也会新建临时list存储数据。只是python提供了更多已封装好,可以直接用的方法。golang只提供了几个基础方法,不够用就需要自己处理。
- golang对存储的数据类型是严格要求的,必须提前声明。
后记:假设一个场景,我们的程序要与外面多家公司的进行数据对接。一时真的无法判断对方提交的数据类型,只能先接收下来再根据具体类型具体处理。但是slice又要求那么严格,这怎么办 ?其实golang还是给我们留了出路的,就是把数据类型定义为空接口。
package main
import (
"fmt"
"reflect"
)
func main() {
// 创建slice的时候,定义存储的数据类型为interface{},即空接口
// 空接口表示可以接收任何类型的数据结构结构,是否有点python中list的味儿了 ?
myintSlice := make([]interface{}, 0)
// 新建纯string的slice
mystringSlice := []string{"a", "b", "c"}
for i := 1; i <= 3; i++ {
// 先塞int 整数进去
myintSlice = append(myintSlice, i)
}
for _, s := range mystringSlice {
// 再塞string进去
myintSlice = append(myintSlice, s)
}
// 检查一些slice的内容
fmt.Println(myintSlice)
for _, x := range myintSlice {
// 验证一下数据类型
fmt.Println(reflect.TypeOf(x))
}
这样就与python的list效果一样了
% go run main.go
[1 2 3 a b c]
int
int
int
string
string
string