Yaklang 的类型其实非常简单,我们仅需要记住如下类型即可
- string 字符串类型,用以快速构建一个字符串
- int 整数类型:在 64 位机中,int 和 int64 是一样的
- float 浮点类型,用来定义和表示浮点数
- byte 本质上等同于 uint8
- undefined / nil 为定义的值,我们可以理解为空值
- bool 只有 true 或 false
- map,基本等同于 Python 中的 Dict
- slice,基本等同于 Python 中的 List
- channel,基本等同于 Golang 中的 Channel
- var,任意类型,等同于 Golang 中的 interface{}
我们以一个表格快速来对比大家熟悉的语言的类型,以方便大家快速理解
对比类型 | Yaklang | Python | Golang |
---|---|---|---|
字符串 | string | string | string |
二进制字符串 | []byte | b-string | []byte |
整数 | int | int | int8, int16, int32, int64 |
uint8, uint16, uint32, uint64 | |||
int | |||
浮点 | float | float | float32, float64(double) |
空值 | undefined / nil | 不支持 | nil |
布尔值 | bool | bool | bool |
键值组(map / dict) | map | dict | map |
数组 / 切片 / 列表 | slice | list | slice / array |
结构体 / 类 / 接口 | 不支持 | class | struct / interface 体系 |
数据通道 | channel | 不支持 | channel |
任意类型 | var | object | interface{} |
变量的声明,定义与使用
在yaklang中定义/声明一个变量十分简单:
var a // 声明变量a
var b, c // 声明变量b,c
var d, e = 1, 2 // 声明变量d,e并分别赋值为1,2
同时,我们可以直接对一个变量进行赋值,省略定义/声明的步骤:
a, b = 1, 2 // 此时a=1, b=2
下面是每一种数据类型的示例:
字符串
// 这是yaklang的字符串类型
a:="这是一个字符串";//一个
// 使用dump函数进行输出
dump(a);
二进制字符串
// 这是yaklang的二进制字符串类型
binaryString := "0b101101";
// 使用dump函数进行输出
dump(binaryString);
整数
注意yaklang中的整数型和golang是一样的。在Go语言中,int64 是一种数据类型,它是一个64位的有符号整型。这意味着它可以存储的整数值的范围是从 -9223372036854775808 到 9223372036854775807(即从 -2^63 到 2^63 - 1)
// c:=213333333333345465467686908680857435243567821345678345678223456789123456789123456789 超过了最大值范围
/**
在Go语言中,int64 是一种数据类型,它是一个64位的有符号整型。这意味着它可以存储的整数值的范围是从 -9223372036854775808 到 9223372036854775807(即从 -2^63 到 2^63 - 1)
*/
c=9223372036854775805
dump(c);
如果超出int64的范围则会报错
d=9223372036854775809;
dump(d);
浮点
浮点型即为小数型
d=1.23465;
dump(d);
空值
什么是空值?字面意思就是没有具体的值。在 Go 语言中,nil 是一个预定义的标识符,用于表示指针、通道、函数、接口、映射或切片类型的零值。nil 并不同于其他语言中的 null 或 None,因为它具体只能用于上述几种类型。基本类型(如 int、float、bool 和 string)以及结构体类型都有自己的零值,例如 0、0.0、false 和 “”,但它们的零值不是 nil。但是Yaklang有一点不太一样,yak不存在“零值”,看下面的代码就知道了
这是golang中的基础数据类型的定义
package main
import "reflect"
func main() {
var a int
reflect.ValueOf(a)
}
可以运行得到“零值”,但是yak则不能这样定义
此外在Yaklang中空值有两种:
- undefined
- nil
在yaklang中,空值表示为 undefined
或 nil
。这两种表示方式都是用来表示一个变量没有被赋值或者一个对象没有某个属性。
首先,我们来看一下undefined
和nil
的区别:
undefined
:表示变量没有被赋值或者对象没有某个属性,它是一个非法的值,不能用于任何有效的操作。nil
:表示变量被赋值为空值,通常用于表示一个对象没有某个属性或者一个数组没有某个元素。
var a;
dump(a)
布尔值
a:=true;
dump(a)
键值组(map / dict)
这个数据类型是常见的一种类型,形式为键名:键名对应的值。
在 Yaklang 中,可以使用 map 关键字来定义一个 Map 类型的变量。Map 是一种键值对的数据结构,其中每个键都映射到一个值。yaklang同样有两种map的定义方式:
使用make函数定义:
# 定义一个 Map 类型的变量
m := make(map[string]int);
dump(m);
使用字面量定义:
# 定义一个 Map 类型的变量
m := map[string]int{"apple": 5, "lettuce": 7};
dump(m);
访问和赋值
要向map中添加新的键值对,可以使用以下语法:
m["key"] = value
例子如下:
# 定义一个 Map 类型的变量
m := make(map[string]int);
dump(m);
m["test"]=123;
dump(m);
要从map中读取值:
value := m["key"]
例子如下:
# 定义一个 Map 类型的变量
m := map[string]int{"apple": 5, "lettuce": 7}
dump(m["apple"]) //quchu apple的值
如果请求的键不存在于map中,Go会返回值类型的零值,而Yaklang则会返回空值
# 定义一个 Map 类型的变量
m := map[string]int{"apple": 5, "lettuce": 7}
dump(m["admin"]) //取出不存在的admin的值
删除map里的某一项
要从map中删除键值对,使用delete内置函数:
delete(m, "key(键名)")
例子如下:
# 定义一个 Map 类型的变量
m := map[string]int{"apple": 5, "lettuce": 7}
delete(m, "apple")
dump(m)
遍历map
可以使用for循环和range关键字遍历map中的所有键值对:
# 定义一个 Map 类型的变量
m := map[string]int{"apple": 5, "lettuce": 7}
for key,value := range m {
println("键名:",key,"键值:",value);
}
数组 / 切片 / 列表
在Go语言中,数组和切片是基础且不同的类型,它们都用于存储元素的序列。Go语言没有内置的列表数据类型,但切片提供类似于动态数组的功能。
切片中的length是该切片中当前已存储的元素个数,切片的容量是该切片指向的数组的元素个数。往一个满了的切片(切片长度=切片容量)中添加新元素会触发创建一个新的数组,并且新数组的容量是原来的2倍,该新数组会将原数组中的元素都拷贝过来,同时将slice中的指针更新到指向新数组
切片(Slice)是对数组一个连续片段的引用,因此它是可变长度的。
使用make创建新切片
使用make创建切片,并指定长度和可选的容量:
s := make([]int, 5) // 长度为5,容量也为5
s := make([]int, 5, 10) // 长度为5,容量为10
PS:容量决定切片上限,长度则是实际上的元素个数。即容量必须大于或等于长度
# 定义一个切片
s := make([]int, 5, 3)
dump(s)
上面这种就是错误的
从数组或切片创建新切片
# 定义一个切片
// s := make([]int, 5, 10)
s := [1,2,3,5,654,67,76,7,68,4]
a := s[1:5]
dump(a) // 创建一个新切片,包含从索引1到索引5的元素,长度是4,容量是10
访问切片元素
和数组一样,可以通过索引访问切片的元素:
# 定义一个切片
s := make([]int, 5, 10)
dump(s[0]) // 获取第一个元素的值
修改切片元素
s[0] = 100 // 设置第一个元素的值为100
例子:
golang与Yaklang之间切片区别
在golang中由于切片是引用类型,修改其元素会影响底层数组和其他引用同一数组的切片,但是在Yaklang中修改切片原数组不受影响
golang中切片的修改
package main
import (
"fmt"
)
func main() {
arr := [5]int{1, 2, 3, 4, 5} //原始数组
s := arr[1:4] //数组产生的切片
b := arr[1:4] //引用同一数组的切片
//fmt.Println(s)
//fmt.Println(b)
//fmt.Println(arr)
s[0] = 10000
s[1] = 10000
fmt.Println("改后", s)
fmt.Println("改后", b)
fmt.Println("改后", arr)
}
Yaklang的切片修改
# 定义一个切片
// s := make([]int, 5, 10)
s := [1,2,3,5,654,67,76,7,68,4]
a := s[0:5]
b := s[0:5]
println("原始切片:",a)
println("原始切片:",b)
println("原始数组:",s)
a[0]=10000
a[1]=10000
println("修改后的切片:",a)
println("修改后的切片:",b)
println("修改切片后的数组:",s)
添加元素
可以使用append函数向切片添加元素。如果添加的元素超出切片容量,Go会自动创建一个新的底层数组,并将元素复制过去:
s = append(s, 6)
例子:
# 定义一个切片
// s := make([]int, 5, 10)
s := [1,2,3,5,654,67,76,7,68,4]
a := s[0:5]
b := s[0:5]
println("原始切片:",a)
println("原始切片:",b)
println("原始数组:",s)
a=append(a,"添加的元素")
println("修改后的切片:",a)
println("修改后的切片:",b)
println("修改切片后的数组:",s)
遍历切片
可以使用for循环或者for配合range关键词来遍历切片:
// 使用for循环
for i := 0; i < len(s); i++ {
fmt.Println(s[i])
}
// 使用for和range
for index, value := range s {
fmt.Println(index, value)
}