Gox语言中的基本数据类型及其转换-GX5.1

Gox语言默认选用Qlang语法引擎,Qlang脚本语言又是基于Go语言(Golang)做了一定的改进,数据类型基本继承自Go语言,数据的赋值等操作也基本类似但略加改进和变化。一个主要的不同是,Gox语言使用动态类型,与Go语言的区别主要体现在:

  • 变量赋值前无需先进行类型声明,例如,下面的都是合法的变量赋值方法,赋值时,Gox语言会自动确定其类型;另外,使用“=”或“:=”都可以,其作用是一样的,“:=”并不像Go语言中一样表示声明变量并赋值的意思,因此,一般建议直接用“=”来进行变量赋值。
a = 1

b = "abc"

  • 同一变量可以被先后赋值为不同的类型,也就意味值在Gox语言中,变量的类型是可变的,这是与Go语言明显的不同。
a = 1

a = "list"

a = true

上面给变量a先后赋给整数、字符串和布尔类型等,都是可以的。

 

大小写敏感

注意,Gox语言也是大小写敏感的,各种标识符(包括变量名、函数名、结构体名等)大小写不同的话,都会被认为是不同的。

 

变量的声明与赋值

Gox语言中,并没有局部变量声明,也就是说,如果已经存在全局变量a,那么在函数体或嵌入代码块中出现同名的变量,都被认为是对全局变量进行操作,这点要特别注意,全局变量起名要比较慎重,建议末尾加大写的G(global的意思)表示区别:

a = 1

fn() {
    a = 2
}()

println(a)

其中,fn是Gox语言中定义函数的关键字,相当于Go语言中的func,或其他语言中的function。println是Gox语言内置的函数,作用是输出信息,与其他语言的println相同。定义好的函数后直接可以加括号来调用,这样是一个匿名函数的定义和执行的方法。这段代码运行后将得到下面的结果:

2

可以看出,全局变量a在匿名函数执行后,值由1变成了2。

而例外的是函数定义中参数的名称会影响这一点,下面这段代码,

b = "I'm fine."

fn(b) {
    b = "Hi!"
}(b)

println(b)

执行结果是:

I'm fine.

可以清楚地看出,由于这段代码中定义的匿名函数需要一个参数,并且名字与全局变量b的名字相同,因此,在这个函数中,对变量b的操作是针对传入函数的变量值来操作的,我们知道,对于传值的参数,在函数内对其进行操作不会影响原始的变量本身,因此函数执行后输出的全局变量b的值仍然没变。

另外注意,带有参数的匿名函数的调用方法,后面的括号中要带上所需的参数,并且fn的函数定义中的b与调用函数时代入的b表示的是两个概念,第一个是函数的形式参数,第二个是指全局变量b,不要搞混淆了。

布尔类型

布尔类型英语中一般称作boolean,也常简称bool,布尔类型数据的取值只有true和false两个值,分别代表真与假、是或否等对立的概念。布尔类型的数值或变量经常被用于条件判断分支代码中。

b = true

printf("[%T] %v\n", b, b)

c = false

printf("[%T] %v\n", c, c)

printf("!b = %v\n", !b)

printf("b == c: %v\n", b == c)

printf("1 > 14: %v\n", 1 > 14)

printf("b == true: %v\n", b == true)

printf("b && c: %v\n", b && c)

printf("b || c: %v\n", b || c)

上面这段代码中,printf函数也是Gox语言的内置函数,与其他语言的printf功能是基本一致,与Go语言中的printf函数完全一样。因此,其中如果要输出回车换行符也要用转义字符“\n”。

这段代码执行后,输出结果如下:

λ gox -gopath test
[bool] true
[bool] false
!b = false
b == c: false
1 > 14: false
b == true: true
b && c: false
b || c: true

其中,可以看出,变量a的值是true,变量b的值是false,“!”是取反(也叫“非”)操作符,如果是false取反则是true,true的取反为false。很多表达式的计算结果也是bool类型的,例如“b==c”表示判断变量b与c中的值是否相等(“==”符号表示判断其两边的变量值是否相等),其结果也是一个bool类型的值,由于b和c中的值并不相等,所以“b == c”的计算结果是false。因此,b == true这个表达式的结果就是true了,因为b的值就是true。“&&”和“||”表示“逻辑与”和“逻辑或”,这与很多其他语言也是一致的,true && true 还是 true,true && false 是 false,false && true 还是 false,false && false 也是 false;而true || true 是 true,true || false 还是 false,false || true 也是 true,false || false 则是 false。

整数类型

c1 = 19

c2 = 18

println(c1 + c2/3)

printfln("%T, %v", c1, c1)

printfln("%T", c1+c2)
printfln("%T", c2/3)
printfln("%T", c1+c2/3)
printfln("%T, %v", (c1+c2/3)*6, (c1+c2/3)*6)

c1++
c1 *= 3

c2 += 5
c2--

printfln("c1: %v, c2: %v, %T", c1, c2, c1)

这段代码的执行结果是:

λ gox -gopath test
25
int, 19
int
int
int
int, 150
c1: 60, c2: 22, int

可以清晰地看出,整数的运算,结果一般来说还是证书。并且整数都是64位的。另外,运算符++、--、*=,+=也都有效(还有-=,/=也都可以使用)。

另外,printfln是Gox语言内置的函数,相当于printf函数并且会在最后多输出一个回车换行符。而“%T”和“%v”是从Go语言中继承过来的格式符,“%T”表示输出后面对应变量的类型,“%v”则是输出任意变量的字符串表示。

Gox语言中也支持int64,uint8,rune等Go语言中常见的类型,在一些函数调用中会使用到,需要的时候可以用下述方式转换:

c1 = 19
c2 = int64(c1)

 

浮点数类型

f1 = 1.32

previus_f1 = f1

f1 = f1 * 0.8

print(previus_f1, "*", 0.8, "=", f1)
println()

f2 = 0.99
f2 /= 0.3

print(0.99, "/", 0.3, "=", f2, "\n")

执行结果为:

λ gox -gopath test
1.32*0.8=1.056
0.99/0.3=3.3000000000000003

需要注意的是,print也是Gox语言的内置函数,功能与其他语言中的print类似,如果要输出回车换行符,可以用本代码中所示的两种方法,一种是加一个没有参数的println函数,另一种是多输出一个转义符“\n”。

 

字符串类型

下面是一些字符串赋值与操作的例子:

s1 = "abc"

s2 = s1 + "3"

pv("s2")

println(s1, "+", "3", "=", s2)

s5 = "上善若水"

pv("s5")

s6 = []byte(s5)

println(s6)

t = rune(5)
pv("t")

s7 = []rune("上善若水")

pv("s7")

pl("s5[1:2] = %#v", s5[1:2])

pl("s6[1:2] = %#v", s6[1:2])

pl("s7[1:2] = %#v", s7[1:2])

pl("string(s7[1:3]) = %#v", string(s7[1:3]))

pl("string([]byte(string(s7[1:3]))) = %#v", string([]byte(string(s7[1:3]))))

pl("%c", s5[1])
pl("%c", s6[1])
pl("%c", s7[1])

pl("%T, %#v", s5[1], s5[1])
pl("%T, %#v", s6[1], s6[1])
pl("%T, %#v", s7[1], s7[1])

for i = 0; i < len(s5); i++ {
    pl("%v: %v", i, s5[i])
}

for v = range s7 {
    pl("%#T, %v", byte(v), byte(v))
}

运行结果是:

λ gox -gopath test                                          
s2(string): abc3                                            
abc + 3 = abc3                                              
s5(string): 上善若水                                            
[228 184 138 229 150 132 232 139 165 230 176 180]           
t(int32): 5                                                 
s7([]int32): [19978 21892 33509 27700]                      
s5[1:2] = "\xb8"                                            
s6[1:2] = []byte{0xb8}                                      
s7[1:2] = []int32{21892}                                    
string(s7[1:3]) = "善若"                                      
string([]byte(string(s7[1:3]))) = "善若"                      
¸                                                           
¸                                                           
善                                                           
int, 184                                                    
int, 184                                                    
int, 21892                                                  
0: 228                                                      
1: 184                                                      
2: 138                                                      
3: 229                                                      
4: 150                                                      
5: 132                                                      
6: 232                                                      
7: 139                                                      
8: 165                                                      
9: 230                                                      
10: 176                                                     
11: 180                                                     
int, 0                                                      
int, 1                                                      
int, 2                                                      
int, 3                                                      

这里需要注意的是:

  • pv函数可以查看变量的名称、类型和值,在调试代码的时候比较方便,但注意函数的参数要求传入变量名称,是个字符串,要加引号;
  • pl函数与printfln作用相同,只是个简写;
  • 字符串加法的意义则是两个字符串连接(或者叫合并)起来;
  • 与Go语言相同,对于UTF-8编码的字符,转成[]rune类型才可以处理正确,因此,要想正确地遍历utf-8字符串,需要转换成[]rune类型(rune类型本质上是int32类型);

 

空类型nil

Gox语言中的空类型实际上用到的场景没有那么多,主要用途有以下几种情况:

  • 用于事先声明一个变量,声明的时候可能无法确定类型或取值;例如定义一个在后面赋值的全局变量时;但实际上Gox语言为了这个目的,可以直接一个变量名就表示声明一个变量;
  • 用于调用Go语言库中会返回nil类型的函数时进行交互和判断,例如常见的error类型;

参看下面的例子:

pv("aaa")

println(aaa)

aaa = 18

pv("aaa")

println("aaa")

b = nil

pv("b")

println(b)

println("------")

c, errT = tk.StrToInt("12ab")

if errT != nil {
    println("Error:", errT.Error())
}

pv("c")

pv("errT")

c, errT = tk.StrToInt("123")

pv("c")

pv("errT")

if errT != nil {
    println("Error:", errT.Error())
}

执行结果为:

aaa(spec.undefinedType): undefined
undefined
aaa(int): 18
aaa
b(<nil>): <nil>
<nil>
------
Error: strconv.ParseInt: parsing "12ab": invalid syntax
c(int): 0
errT(*strconv.NumError): strconv.ParseInt: parsing "12ab": invalid syntax
c(int): 123
errT(<nil>): <nil>

代码中的tk.StrToInt函数就是会返回error类型值得函数,当传入参数的字符串无法被转换为整数类型时,返回的第二个值(error类型)将不是nil,而可以正常转换时,将返回nil值。

另外注意,Gox语言中,如果没有定义一个变量就直接被引用(而不是赋值),会得到undefined这个值,与Javascript语言有些类似。在Go语言中,这样的用法将产生panic。当然,条件判断的时候也可用

if a == undefined {...}

来进行判断。对于数组和映射(map)中也是用undefined来确定其中是否有所需索引的值和键值的,例如:

m = map[string]string{"a": "1", "b": "ABC"}

v1 = m["a"]
pl("v1: %#v", v1)

v2 = m.a
pl("v2: %#v", v2)

v3 = m["c"]
pl("v3: %#v", v3)

if v3 == undefined {
    pln("v3 is undefined")
}

运行结果是:

λ gox -gopath test
v1: "1"
v2: "1"
v3: 0
v3 is undefined

可以看出undefined的使用方法和其输出时的显示值。

 

数据类型的转换

Gox语言中可以使用int(a)、string(s)等与Go语言中类似的方式进行数据类型转换,某些不能直接进行类型转换的,需要用一些其他函数来执行转换动作。另外,可以用内置函数type来获取某个变量的类型。下面的例子代码展示了这些用法。

a = 1
b = int64(2)

println("type of a is:", type(a))
println("type of b is:", type(b))

println("a + b =", a+b)
printfln("a + b = %#v", a+b)

a1 = tk.IntToStr(a)
b1 = tk.IntToStr(b)

printfln("type of a1 is: %T", a1)
printfln("value of a1 is: %v", a1)
printfln("internal value of a1 is: %#v", a1)

println("a1 + b1 =", a1+b1)
printfln("a1 + b1 = %#v", a1+b1)

a2 = tk.StrToFloat64WithDefaultValue(a1, 0)
b2 = tk.StrToFloat64WithDefaultValue(b1, 0)

printfln("a2 + b2 = %#v", a2+b2)
printfln("type of a2 + b2 is: %T", a2+b2)

运行结果为:

λ gox -gopath test
type of a is: int
type of b is: int64
a + b = 3
a + b = 3
type of a1 is: string
value of a1 is: 1
internal value of a1 is: "1"
a1 + b1 = 12
a1 + b1 = "12"
a2 + b2 = 3
type of a2 + b2 is: float64