0x01 基本类型
对比C语言的基本数据类型
C语言:int、char、float(保留小数点后7位,4个字节)、double(保留小数点后15位,八个字节)
Yak语言:int、float(类似于Go语言中float64,等价于C语言中的double类型)、string、byte、bool、var
代码理解(官方解释代码):
a = 1 // 整数类型
b = "CV is handsome" // string 类型
c = true // bool 类型
d = 1.0 // float 类型
e = 'c' // byte 类型,理解为占一个字节,同C语言的char类型
f = var // f 为一个兼容类型,意思就是遇到值为整型,则就是整型;遇到其他类型同理。
强制转换
type(value)
代码理解(官方解释代码):
a = int(1.2) //a的值为1,类型为int型
b = 1.2 //b的值为1.2,类型为float型
c = int(b) //c的值为1,类型为int型
0x02 复合类型
1)slice类型
官方解释:用于以列表的形式存储元素的数据类型 (等效于 Python 的 list
),同 Golang 中的 slice。
个人理解:类似于数组。
代码理解(以下均为官方解释代码):
创建slice类型
b = [1, 2.3, 5] // 创建一个 []float(因为有一个float类型,所以默认为float数组)
c = ["a", "b", "c"] // 创建一个 []string
d = ["a", 1, 2.3] // 创建一个 []var (等价于 Go 语言的[]interface{})
e = make([]int, 3, 3) // 创建一个 []int,并将长度设置为 3,容量设置为 3
f = make([][]int, 3, 3) // 创建一个 [][]int,并将长度设置为 3,容量设置为 3
g = []byte{1, 2, 3} // 创建一个 byte slice,并初始化为 [1, 2, 3]
h = []byte(nil) // 创建一个空 byte slice
总结官方代码:
make()函数创建某种类型,[]创建数组也可以说是列表;如果[]没有定义类型,则会自动判断类型,如果有整数、小数、字符等,类型则是var型;如果有整数和小数,类型则是float型,其原因作者个人认为与C语言中相同,如果有大字节,统一按照大字节类型定义。比如,int类型如果是2字节,float如果是4字节,在定义数组时,同时出现了int类型和float类型,则默认按照4字节处理,这时会将int类型转换成float类型。
科普一下,为什么在int类型和float类型同时出现在一个运算式中,结果为float型。其实这里注意一点,如果是float类型的数据转换成int类型,肯定要丢失数据。解释:假设float为8字节,int为4字节,float转换成int,则需要丢失4字节的空间,所以在很多语言中,就算int和float的字节相同,也会转换成float型,已经成为一个约定俗成的规则了。
添加元素
a=append(a,1,2,3)
append(target,value...)函数作用是添加元素。
a = append([1,2,3], 5,6,7)
length = len(a)
println("len(a): ", length)
capValue = cap(a)
println("cap(a): ", capValue)
// OUTPUT:
// len(a): 6
// cap(a): 6
len()函数获取目标变量元素个数,cap()函数获得目标变量容量。
复制
copy(sliceA,sliceB)把B中的元素复制到A中
a = [1,2,3]
b = [4,5,6,7,8]
copiedCount = copy(a, b)
println("copy(a, b) returns ", copiedCount)
println("slice a now: ", a)
// OUTPUT:
// copy(a, b) returns 3
// slice a now: [4 5 6]
按索引获取数组元素,与python中的语法类似。
a = [1,2,3,4,5,6,7,8]
b = a[4:6]
c = a[:5]
d = a[3:]
index1 = a[1]
index2, index3 = a[2], a[3]
println("b: ", b)
println("c: ", c)
println("d: ", d)
println("a[1]: ", index1)
println("a[2]: ", index2)
println("a[3]: ", index3)
//运行结果:
//b: [5 6]
//c: [1 2 3 4 5]
//d: [4 5 6 7 8]
//a[1]: 2
//a[2]: 3
//a[3]: 4
2)map类型
官方解释:用于以键值对的形式存储数据的结构(等效于 Python 中的 dict
),同 Golang 中的 map。
个人理解:可以参考JSON数据。
代码理解(以下均为官方解释代码):
创建map变量
// 得到 map[string]int 类型的对象
a = {"a": 1, "b": 2, "c": 3}
// 得到 map[string]float64 类型的对象
b = {"a":1,"b":2.3,"c": 3}
// 得到 map[int]string 类型的对象
c = {1: "a", 2: "b", 3: "c"}
// 得到 map[string]interface{} 类型的对象
d = {"a": "hello", "b": 2.0, "c": true}
// 创建一个空的 map[string]int 类型的对象
e = make(map[string]int)
// 创建一个map[string]map[string]int 类型的对象
f = make(map[string]map[string]int)
// 创建一个 map[string]int16 类型的对象
g = map[string]int16{"a": 1, "b": 2}
// 创建一个 map[string]interface{}
x = {}
// 创建一个 map[interface{}]interface{}
x = make(map[var]var)
map的特征{key:value...},所以创建特征符合map类型,则创建的变量就为map类型。
map的基本用法
a = {"a": 234, "b": "sasdfasdf", "ccc": "13"} // 我们创建一个 map[var]var
n = len(a) // 取 a 的元素个数
println("len(a): ", n)
// OUTPUT: len(a): 3
x = a["b"] // 取 a map 中 key 为 "b" 的元素
println(`a["b"]: `, x)
// OUTPUT: a["b"]: sasdfasdf
a.noSuchKey // 如果取一个不存在的 key,直接通过 .keyName 调用则会报错,退出程序
// OUTPUT:
// [ERRO] 2021-05-25 20:38:04 +0800 [default:yak.go:100] line 58: member `noSuchKey` not found
// 当然,我们也可以把拆包解包用在 map 中
a["e"], a["f"], a["g"] = 4, 5, 6 // 同 Go 语言
a.e, a.f, a.g = 4, 5, 6 // 含义同 a["e"], a["f"], a["g"] = 4, 5, 6
// 如果你想要删掉 map 中的某个元素
a = {"a": 123, "b": 1345, "c": 999}
println("a.b: ", a.b)
delete(a, "b")
println("NOW map a: ")
dump(a)
/*
a.b: 1345
NOW map a:
(map[string]int) (len=2) {
(string) (len=1) "a": (int) 123,
(string) (len=1) "c": (int) 999
}
*/
3)chan类型
官方解释:Yak 与 Golang 特有的复合数据类型,通过 make(chan <T>)
创建,<T>
为这个 chan 数据通道传输的数据类型,可以类比为 Python 中的 Queue。
个人理解:将chan理解成一个仓库,进行的操作都是数据的出仓和入仓,在上一节课中有讲到。其实chan是建立一个缓冲区。
创建chan类型
ch1 = make(chan bool, 2) // 得到 buffer = 2 的 chan bool
ch2 = make(chan int) // 得到 buffer = 0 的 chan int
ch3 = make(chan map[string]int) // 得到 buffer = 0 的 chan map[string]int
这里需要注意的是,chan类型只能通过make()函数创建,与Go语言用法相同。
基本用法
/*创建一个 chan var*/
ch1 = make(chan var, 4)
ch1 <- 1
ch1 <- 2
// 一通操作
n = len(ch1) // 取得chan当前的元素个数
m = cap(ch1) // 取得chan的容量
v = <-ch1 // 从chan取出一个值
close(ch1) // 关闭chan,被关闭的chan是不能写,但是还可以读(直到已经写入的值全部被取完为止)
v1 = <- ch1
v2 = <- ch1
// 查看操作的结果和特性
println("len(ch1): ", n)
println("cap(ch1): ", m)
println("<-ch1 执行第一次: ", v)
println("<-ch1 执行第二次: ", v1)
println("<-ch1 执行第三次: ", v2)
//运行结果
//len(ch1): 2
//cap(ch1): 4
//<-ch1 执行第一次: 1
//<-ch1 执行第二次: 2
//<-ch1 执行第三次: undefined
课件参考来源于Yak官网,最后想要学习Yak语言的大佬可以关注微信公众号:乌托邦安全团队,后面会持续更新Yak相关的学习经验。
公众号输入Yak教程第二课,获取当前课件。
作者:CV
原文始发于微信公众号(乌托邦安全团队):Yak之数据类型
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论