一、 基本数据类型
1、整型
和其它大部分编程语言一样,在go语言中,整型同样可分为有符号型和无符号型。其中,有符号整型又分为int8、int16、int32和int64,同样,无符号整型也可分为uint8、uint16、uint32和uint64。另外,还根据不同CPU平台有不同取值范围的int和uint两种,在32位字节码CPU中,int与int32一样,uint与uint32一样,而在64位字节码CPU中,int与int64一样,uint与uint64一样。
各整型的取值范围:
类型 | 取值范围 |
---|---|
int8 | -128到127,即-(27)到(27-1) |
uint8 | 0到255,即0到(28-1) |
int16 | -32768到32767,即-(215)到(215-1) |
uint16 | 0到65535,即0到(216-1) |
int32 | -2147483648到2147483647,即-(231)到(231-1) |
uint32 | 0到4294967295,即0到(232-1) |
int64 | -9223372036854775808到9223372036854775807,即-(263)到(263-1) |
uint64 | 0到18446744073709551615,即0到(264-1) |
其中,根据平台不一样,int和uint的取值也不一样,具体可参考上表。
使用math下的常量定义,我们可以验证上表是否正确:
package main
import (
"fmt"
"math"
)
/*
整型变量取值范围
*/
func main() {
fmt.Println("MinInt8:", math.MinInt8)
fmt.Println("MaxInt8:", math.MaxInt8)
fmt.Println("MaxUint8", math.MaxUint8)
fmt.Println("MinInt16:", math.MinInt16)
fmt.Println("MaxInt16:", math.MaxInt16)
fmt.Println("MaxUint16:", math.MaxUint16)
fmt.Println("MinInt32:", math.MinInt32)
fmt.Println("MaxInt32:", math.MaxInt32)
fmt.Println("MaxUint32:", math.MaxUint32)
fmt.Println("MinInt64:", math.MinInt64)
fmt.Println("MaxInt64:", math.MaxInt64)
// fmt.Printf("MaxUint64:%d", math.MaxUint64)
}
运行结果:
可以看到,有符号整型的取值范围与上表中是一致的。而程序在输出MaxUint64时,终端提示“constant 18446744073709551615 overflows int”,大概意思是数据越界了,但至少可以看出,上表中的取值范围是正确的。至于错误如何解决,惭愧的表示暂时还不清楚,希望在继续的学习过程中,能找到解决错误的办法。如果读者朋友能留言指点一二,那就真是三生有幸了!
2、浮点型
浮点型只为float32和float64两种,没有C语言中的double类型。
类型 | 取值范围 |
---|---|
float32 | 3.4028234663852886e+38 |
float64 | 1.7976931348623157e+308 |
我们同样可以编写程序验证:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println("MaxFloat32:", math.MaxFloat32)
fmt.Println("MaxFloat64:", math.MaxFloat64)
}
运行结果:
同样可以验证浮点型的取值范围是正确的。
3、布尔型
如果你是做C语言开发的,那你一定知道在C语言中,没有布尔型变量,而是用0表示假,非0表示真。而在go中不一样了,go中增加了布尔值类型,它只有true和false两种取值。
我们同样和程序来验证:
package main
import "fmt"
func main() {
fmt.Println("结果:", 1 < 2)
fmt.Println("结果:", 1 > 2)
}
输出如下:
很明显,1小于2为真,输出结果为true,1大于2为假,输出结果为false。
二、 变量
变量,是指不固定的,可改变的数据。变量名,用来保存变量的值。
1、变量的定义方式
go语言中,变量的定义使用关键字var修饰。变量定义有以下几种方式:
1.var 变量名 数据类型[ = 变量初始值]
2.变量名 := 变量初始值
3.var (
变量名 数据类型[ = 变量初始值]
)
其中第2种方式只能用于局部变量的定义。见测试代码:
package main
import (
"fmt"
)
var x int = 10
var (
i int
j float32
)
func main() {
y := 10
var z int = 20
var (
m int
n float32
)
fmt.Println("x = ", x)
fmt.Println("i = ", i)
fmt.Println("j = ", j)
fmt.Println("y = ", y)
fmt.Println("z = ", z)
fmt.Println("m = ", m)
fmt.Println("n = ", n)
}
输出:
2、全局变量
定义在函数外部的变量,就是全局变量。在该文件下的所有函数都可以访问。
package main
import (
"fmt"
)
var i int
func main() {
i = 100
fmt.Println("i = ", i)
}
输出:
当有多个全局变量需要定义时,可以一个一个变量定义,也可以使用更简捷的定义方式:
package main
import (
"fmt"
)
var (
i int
j int
)
func main() {
i = 100
j = 90
fmt.Println("i = ", i)
fmt.Println("j = ", j)
}
输出:
当然,上述简捷的定义方式是可以定义不同的变量类型的:
package main
import (
"fmt"
)
var (
i int
j int
f float32
)
func main() {
i = 100
j = 90
f = 8.909
fmt.Println("i = ", i)
fmt.Println("j = ", j)
fmt.Println("f = ", f)
}
输出:
3、局部变量
局部变量是指在{}内部的变量,在定义语句执行后分配空间,{}内代码执行完毕后释放空间,不能再使用:
package main
import (
"fmt"
)
func main() {
{
var i int = 100
fmt.Println("i = ", i)
}
}
输出:
修改下程序,在外面调用i时,会发生什么呢?
package main
import (
"fmt"
)
func main() {
{
var i int = 100
fmt.Println("i1 = ", i)
}
fmt.Println("i2 = ", i)
}
输出:
可以看到,此时运行程序发生错误,提示为i未定义。
三、 常量
常量,是指定义之后不能变的量。
1、常量的定义方式
go语言中,常量使用const关键字修饰。常量的定义有以下几种方式:
1.var 变量名 数据类型 = 变量初始值
2.var (
变量名 数据类型 = 变量初始值
)
可以看到,与变量的定义相比,常量的定义方式更少,且要求更高,定义时必须赋值:
package main
import (
"fmt"
)
const a = 100 //定义常量a
const b int = 1000
const (
x = 1
y float32 = 2.0
)
func main() {
fmt.Println("a = ", a)
fmt.Println("b = ", b)
fmt.Println("x = ", x)
fmt.Println("y = ", y)
}
输出:
与变量的定义相比,常量的定义多了一些限制:
1) 定义时,赋值操作是不能省略的;
2) 不支持“:=”的赋值操作
一般的,我们使用全大写字母来代表常量,这样,在看代码的时候可以一眼看出常量还是变量,提高代码的可读性:
package main
import (
"fmt"
)
const PI = 3.14
func main() {
fmt.Println("半径为2的圆的周长为:", 2*PI*2)
}
输出:
2、全局常量
参考全局变量。
3、局部常量
参考局部变量。
四、运算符
go语言内置的运算符分为:
算术运算符;
关系运算符;
逻辑运算符;
位运算符;
赋值运算符;
下面分别介绍各个运算符。
算术运算符
算术运算符有加(+)、减(-)、乘(*)、除(/)、取余(%)、自增(++)、自减(--)七种。
加、减、乘三种运算和小学学习的数学运算没有任何区别:
package main
import (
"fmt"
)
func main() {
fmt.Println("1 + 2 = ", 1+2)
fmt.Println("5 - 2 = ", 5-2)
fmt.Println("10 * 2 = ", 10*2)
}
输出:
除法运算,要求除数不能为0。如果除数和被除数都是整型,那么结果也是整型,小数部分将会被丢掉。而如果其中有一个数为浮点型,那结果就是浮点型:
package main
import (
"fmt"
)
func main() {
fmt.Println("10 / 3 = ", 10/3)
fmt.Println("10 / 3.0 = ", 10/3.0)
fmt.Println("10.0 / 3 = ", 10.0/3)
}
输出:
取余运算,顾名思义,就是取余数运算:
package main
import (
"fmt"
)
func main() {
fmt.Println("10 % 3 = ", 10%3)
fmt.Println("10 % 2 = ", 10%2)
}
输出:
当然,浮点数是不能进行取余运算的,否则编译会出错:
package main
import (
"fmt"
)
func main() {
fmt.Println("10 % 3.0 = ", 10%3.0)
fmt.Println("10.0 % 3 = ", 10.0%3)
}
输出:
可以看到,浮点数据进行取余计算,编译提示非法的表达式。
自增运算,即自己加1后再赋值给自己;同样,自减运算,即自己减1后再赋值给自己:
package main
import (
"fmt"
)
func main() {
i := 1
i++
fmt.Println("i = ", i)
//下面的语句编译报错"syntax error: unexpected ++, expecting comma or )",为什么?
// fmt.Println("i = ", i++)
j := 1
fmt.Println("j = ", j+1)
}
输出:
关系运算符
关系运算符有等于(==)、大于(>)、小于(<)、不等于(!=)、小于等于(<=)、大于等于(>=)六种,关系运算的结果为布尔值,即只有true或false两种结果:
package main
import (
"fmt"
)
func main() {
fmt.Println("1 == 2 结果:", 1 == 2)
fmt.Println("1 > 2 结果:", 1 > 2)
fmt.Println("1 < 2 结果:", 1 < 2)
fmt.Println("1 != 2 结果:", 1 != 2)
fmt.Println("1 <= 2 结果:", 1 <= 2)
fmt.Println("1 >= 2 结果:", 1 >= 2)
}
输出:
逻辑运算符
逻辑运算符分为与(&&)、或(||)、非(!)三种,运算符两边必须为布尔值,否则编译时会出现“invalid operation”错误。
其中与运算相当于并且的意思,只有两边都为真是,运算结果才为真;或运算相当于或者的意思,两边有一个为真,结果就为真;非运算,即真变假,假变真:
package main
import (
"fmt"
)
func main() {
//与运算
fmt.Println("true && true 结果:", true && true)
fmt.Println("true && false 结果:", true && false)
fmt.Println("false && true 结果:", false && true)
fmt.Println("false && false 结果:", false && false)
fmt.Println("---------------------------")
//或运算
fmt.Println("true || true 结果:", true || true)
fmt.Println("true || false 结果:", true || false)
fmt.Println("false || true 结果:", false || true)
fmt.Println("false || false 结果:", false || false)
fmt.Println("---------------------------")
//非运算
fmt.Println("!true 结果:", !true)
fmt.Println("!false 结果:", !false)
}
输出:
位运算符
位运算可分为按位与(&)、按位或(|)、按位异或(^)、左移(<<)、右移(>>)五种。
说到位运算,就需要先了解数的进制。一般在我们日常生活中使用的都是十进制数,而计算机根本不认识十进制数,所以我们需要将十进制转换成2进制,一字节(1byte)是由八位(8bit)组成,1bit就是一位,所以,位运算操作的是字节里的每一位:
package main
import (
"fmt"
)
func main() {
//假设变量a的值为10,变量b的值为20,那么位两个变量进行位运算后的结果是多少呢?
var a int = 10
var b int = 20
fmt.Println("a & b = ", a&b)
fmt.Println("a | b = ", a|b)
fmt.Println("^a = ", ^a)
fmt.Println("^b = ", ^b)
}
输出:
结果分析,十进制10转换成二进制是0000 1010,十进制的20转换成二进制是0001 0100,按位与,即(0000 1010)&( 0001 0100) = (0000 0000),再转换成十进制,结果就是0。同样,(0000 1010)|( 0001 0100) = (0001 1110),再转换成十进制,结果即等于30。(0000 1010)按位取反的二进制结果是11110101,补码(除符号位外的其它位取反后加1)为10001011,转换成十进制结果等于-11。同样,(0001 0100)按位取反的结果是11101011,补码为10010101,转换成十进制结果等于-21。
左移运算和右移运算,相当于乘2运算和除2运算:
package main
import (
"fmt"
)
func main() {
var a int = 10
var b int = 20
fmt.Println("a << 1 = ", a<<1)
fmt.Println("b >> 1 = ", b>>1)
}
输出:
赋值运算符
赋值运算可分为等于、加等于、减等于、乘等于、除等于、取余等于、左移等于、右移等于、按位与等于、按位或等于、按位异或等于几种。
格式:变量名 赋值运算符 值,即变量现在的值做相应的运算之后,再赋值给变量。
其中,移位赋值要求变量数据类型为无符号型,否则,编译会报错“invalid operation”:
package main
import (
"fmt"
)
func main() {
var a int = 1
var b int = 2
var c = a + b
//等于
fmt.Println("c 结果:", c)
//加等于
a = 1
b = 2
a += b
fmt.Println("a += b 结果:", a)
//减等于
a = 1
b = 2
a -= b
fmt.Println("a -= b 结果:", a)
//乘等于
a = 1
b = 2
a *= b
fmt.Println("a *= b 结果:", a)
//除等于
a = 1
b = 2
a /= b
fmt.Println("a /= b 结果:", a)
//取余等于
a = 1
b = 2
a %= b
fmt.Println("a %= b 结果:", a)
//左移等于
var m uint = 1
var n uint = 2
m <<= n
fmt.Println("m <<= n 结果:", m)
//右移等于
m = 1
n = 2
m >>= n
fmt.Println("m >>= n 结果:", m)
//按位与等于
a = 1
b = 2
a &= b
fmt.Println("a &= b 结果:", a)
//按位或等于
a = 1
b = 2
a |= b
fmt.Println("a |= b 结果:", a)
//按位异或等于
a = 1
b = 2
a ^= b
fmt.Println("a ^= b 结果:", a)
}
输出:
当然,基本数据类型还有字符串类型,运算符也还有指针运算和取地址运算,之所以本次学习内容未作记录,是因为后续随着学习的慢慢深入,再详细了解相关的内容。
好了,本次的学习内容就结束了。
学习贵在持之以恒,我们一起加油吧!