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