go语言基本数据类型和变量

简介: go语言基本数据类型和变量

变量

Go 是静态类型语⾔,不能在运⾏期改变变量类型。

使⽤关键字 var 定义变量,⾃动初始化为零值。如果提供初始化值,可省略变量类型,由编译器⾃动推断。

var

声明变量的一般形式是使用 var 关键字: var identifier type 。

var x int
var f float32 = 1.6
var s = "abc"

:=

在函数内部,可⽤更简略的 “:=” ⽅式定义变量,

func main() {
  x := 123
  n, s := 0x1234, "Hello, World!"
  b := 123
  b := 1234 //会出现错误no new variables on left side of := 。因为在上一行已经定义过变量
  println(x, n, s, b)
}

变量赋值

多变量赋值时,先计算所有相关值,然后再从左到右依次赋值。

data, i := [3]int{0, 1, 2}, 0 
i, data[i] = 2, 100 // (i = 0) -> (i = 2), (data[0] = 100) 

特殊只写变量 “_”,⽤于忽略值占位。

func test() (int, string) {
 return 1, "abc"
}
func main() {
 _, s := test()
 println(s)
}

注意

在go语言中交换两个变量的值十分容易,不需要像c语言中定义一个中间量

i,j = j,i

匿名变量 “_”

我们在使用传统的强类型语言编程时,经常会出现这种情况,即在调用函数时为了获取一个值,却因为该函数返回多个值而不得不定义一堆没用的变量。在Go中这种情况可以通过结合使用多重返回和匿名变量来避免这种丑陋的写法,让代码看起来更加优雅。

而且,在go语言中编译器会将未使⽤的局部变量当做错误,为了避免这种情况必须用匿名变量进行占位。

var s string // 全局变量没问题。
func GetName() (firstName, lastName, nickName string) { 
 return "May", "Chan", "Chibi Maruko" 
} 
func main() {
//若只想获得nickName,则函数调用语句可以用如下方式编写:
 _, _, nickName := GetName() 
 i := 0 // Error: i declared and not used。(可使⽤ "_ = i" 进行占位)
}

注意重新赋值与定义新同名变量的区别

s := "abc"
println(&s)
s, y := "hello", 20 // 重新赋值: 与前 s 在同⼀层次的代码块中,且有新的变量被定义。
println(&s, y) // 通常函数多返回值 err 会被重复使⽤。
{
 s, z := 1000, 30 // 定义新同名变量: 不在同⼀层次代码块。
 println(&s, z)
}

输出:

0x2210230f30

0x2210230f30 20

0x2210230f18 30

常量

注意大写字母开头的常量在包外可见,否则只在本包内可见。

常量定义

常量值必须是编译期可确定的数字、字符串、布尔值。

const x, y int = 1, 2 // 多常量初始化
const s = "Hello, World!" // 类型推断
const ( // 常量组
 a, b = 10, 100
 c bool = false
)
func main() {
 const x = "xxx" // 未使⽤局部常量不会引发编译错误。
}

在常量组中,如不提供类型和初始化值,那么视作与上⼀常量相同。

const (
 s = "abc"
 x // x = "abc"
)

常量值还可以是 len、cap、unsafe.Sizeof 等编译期可确定结果的函数返回值。

const (
 a = "abc"
 b = len(a)
 c = unsafe.Sizeof(b)
)

预定义常量

Go语言预定义了这些常量:true、false和iota。

iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1。从以下的例子可以基本理解iota的用法:

const ( // iota被重设为0
 c0 = iota // c0 == 0 
 c1 = iota // c1 == 1 
 c2 = iota // c2 == 2 
) 
const ( 
 a = 1 << iota // a == 1 (iota在每个const开头被重设为0) 
 b = 1 << iota // b == 2 
 c = 1 << iota // c == 4 
) 
const ( 
 u = iota * 42 // u == 0 
 v float64 = iota * 42 // v == 42.0 
 w = iota * 42 // w == 84 
) 
const x = iota // x == 0 (因为iota又被重设为0了) 
const y = iota // y == 0 (同上) 

如果两个const的赋值语句的表达式是一样的,那么可以省略后一个赋值表达式。因此,上

面的前两个const语句可简写为:

const ( // iota被重设为0
 c0 = iota // c0 == 0 
 c1 // c1 == 1 
 c2 // c2 == 2 
) 
const ( 
 a = 1 <<iota // a == 1 (iota在每个const开头被重设为0) 
 b // b == 2 
 c // c == 4

枚举

const (
 Sunday = iota // 0
 Monday // 1,通常省略后续⾏表达式。
 Tuesday // 2
 Wednesday // 3
 Thursday // 4
 Friday // 5
 Saturday // 6
)

可通过⾃定义类型来实现枚举类型限制。

type Color int
const (
 Black Color = iota
 Red
 Blue
)
func test(c Color) {}
func main() {
 c := Black
 test(c)
 x := 1
 test(x) // Error: cannot use x (type int) as type Color in function argument
 test(1) // 常量会被编译器⾃动转换。
}

基本类型

Go语言内置以下这些基础类型:

 布尔类型:bool。

 整型:int8、byte、int16、int、uint、uintptr等。

 浮点类型:float32、float64。

 复数类型:complex64、complex128。

 字符串:string。

 字符类型:rune。

 错误类型:error。

此外,Go语言也支持以下这些复合类型:

 指针(pointer)

 数组(array)

 切片(slice)

 字典(map)

 通道(chan)

 结构体(struct)

 接口(interface)

在这些基础类型之上Go还封装了下面这几种类型:int、uint和uintptr等。这些类型的

特点在于使用方便,但使用者不能对这些类型的长度做任何假设。对于常规的开发来说,用int和uint就可以了,没必要用int8之类明确指定长度的类型,以免导致移植困难。

布尔类型

Go语言中的布尔类型与其他语言基本一致,关键字也为bool,可赋值为预定义的true和

false示例代码如下:

var v1 bool
v1 = true
v2 := (1 == 2) // v2也会被推导为bool类型

布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换。以下的示例是一些错误的用法,会导致编译错误:

var b bool
b = 1 // 编译错误
b = bool(1) // 编译错误
//以下的用法才是正确的:
var b bool
b = (1!=0) // 编译正确 
fmt.Println("Result:", b) // 打印结果为Result: true 

整型

整型是所有编程语言里最基础的数据类型。

类 型 长度(字节) 值 范 围
int8 1 128 ~ 127
uint8(即byte) 1 0 ~ 255
int16 2 32 768 ~ 32 767
uint16 2 0 ~ 65 535
int32 4 -2147 483 648 ~ 2 147 483 647
uint32 4 0 ~ 4 294 967 295
int64 8 9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807
uint64 8 0 ~ 18 446 744 073 709 551 615
int 平台相关 平台相关
uint 平台相关 平台相关
uintptr 同指针 在32位平台下为4字节,64位平台下为8字节

需要注意的是,int和int32在Go语言里被认为是两种不同的类型,编译器也不会帮你自动

做类型转换,比如以下的例子会有编译错误:

var value2 int32
value1 := 64 // value1将会被自动推导为int类型
value2 = value1 // 编译错误

编译错误类似于:

cannot use value1 (type int) as type int32 in assignment。
• 1

使用强制类型转换可以解决这个编译错误:

value2 = int32(value1) // 编译通过

当然,在做强制类型转换时,需要注意数据长度被截短而发生的数据精度损失(比如

将浮点数强制转为整数)和值溢出(值超过转换的目标类型的值范围时)问题。

数值运算

Go语言支持下面的常规整数运算:+、-、*、/和%。加减乘除就不详细解释了,需要说下的是,% 和在C语言中一样是求余运算,比如:

5 % 3 // 结果为:2 
  1. 比较运算
    Go语言支持以下的几种比较运算符:>、<、==、>=、<=和!=。这一点与大多数其他语言相同,与C语言完全一致。
    下面为条件判断语句的例子:
i, j := 1, 2 
if i == j { 
 fmt.Println("i and j are equal.") 
} 

两个不同类型的整型数不能直接比较,比如int8类型的数和int类型的数不能直接比较,但

各种类型的整型变量都可以直接与字面常量(literal)进行比较,比如:

var i int32
var j int64
i, j = 1, 2 
if i == j { // 编译错误
 fmt.Println("i and j are equal.") 
} 
if i == 1 || j == 2 { // 编译通过
 fmt.Println("i and j are equal.") 
} 

位运算

运 算 含 义 样 例
x << y 左移 124 << 2 // 结果为496
x >> y 右移 124 >> 2 // 结果为31
x ^ y 异或 124 ^ 2 // 结果为126
x & y 与 124 & 2 // 结果为0
x | y 124
^x 取反 ^2 // 结果为-3

Go语言的大多数位运算符与C语言都比较类似,除了取反在C语言中是~x,而在Go语言中是^x。

浮点型

浮点型用于表示包含小数点的数据,比如1.234就是一个浮点型数据。

浮点数表示

Go语言定义了两个类型float32和float64,其中float32等价于C语言的float类型,

float64等价于C语言的double类型。

在Go语言里,定义一个浮点数变量的代码如下:

var fvalue1 float32
fvalue1 = 12 
fvalue2 := 12.0 // 如果不加小数点,fvalue2会被推导为整型而不是浮点型

浮点数比较

因为浮点数不是一种精确的表达方式,所以像整型那样直接用==来判断两个浮点数是否相等是不可行的,这可能会导致不稳定的结果。

下面是一种推荐的替代方案:

import "math" 
// p为用户自定义的比较精度,比如0.00001 
func IsEqual(f1, f2, p float64) bool { 
 return math.Fdim(f1, f2) < p 
} 

复数类型

复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部(real),一个表示虚部(imag)。如

复数表示

复数表示的示例如下:

var value1 complex64 // 由2个float32构成的复数类型
value1 = 3.2 + 12i 
value2 := 3.2 + 12i // value2是complex128类型
value3 := complex(3.2, 12) // value3结果同 value2 

实部与虚部

对于一个复数z = complex(x, y),就可以通过Go语言内置函数real(z)获得该复数的实

部,也就是x,通过imag(z)获得该复数的虚部,也就是y。

字符串

在Go语言中,字符串也是一种基本类型。相比之下, C/C++语言中并不存在原生的字符串类型,通常使用字符数组来表示,并以字符指针来传递。

Go语言中字符串的声明和初始化非常简单,举例如下:

str = "Hello world" // 字符串赋值
ch := str[0] // 取字符串的第一个字符
fmt.Printf("The length of \"%s\" is %d \n", str, len(str)) 
fmt.Printf("The first character of \"%s\" is %c.\n", str, ch) 

输出结果为:

The length of “Hello world” is 11

The first character of “Hello world” is H.

字符串的内容可以用类似于数组下标的方式获取,但与数组不同,字符串的内容不能在初始化后被修改,比如以下的例子:

str := "Hello world" // 字符串也支持声明时进行初始化的做法
str[0] = 'X' // 编译错误

编译器会报类似如下的错误:

cannot assign to str[0]

保存源文件时请注意编码格式必须选择UTF-8。特别是在Windows下一般编辑器都默认存为本地编码,比如中国地区可能是GBK编码而不是UTF-8,如果没注意这点在编译和运行时就会出现一些意料之外的情况。

字符串操作

运 算 含 义 样 例
x + y 字符串连接 “Hello” + “qwe” // 结果为Helloqwe
len(s) 字符串长度 len(“Hello”) // 结果为5
s[i] 取字符 “Hello” [1] // 结果为’e’

字符串遍历

Go语言支持两种方式遍历字符串。一种是以字节数组的方式遍历:

str := "Hello,世界"
n := len(str) 
for i := 0; i < n; i++ { 
 ch := str[i] // 依据下标取字符串中的字符,类型为byte 
 fmt.Println(i, ch) 
} 

这个例子的输出结果为:

0 72

1 101

2 108

3 108

4 111

5 44

6 32

7 228

8 184

9 150

10 231

11 149

12 140

可以看出,这个字符串长度为13。尽管从直观上来说,这个字符串应该只有9个字符。这是因为每个中文字符在UTF-8中占3个字节,而不是1个字节。

另一种是以Unicode字符遍历:

str := "Hello,世界"
for i, ch := range str { 
 fmt.Println(i, ch)//ch的类型为rune 
} 

输出结果为:

0 72

1 101

2 108

3 108

4 111

5 44

6 32

7 19990

10 30028

字符类型

在Go语言中支持两个字符类型,一个是byte(实际上是uint8的别名),代表UTF-8字符串的单个字节的值

var ch int = '\u0041'
var ch2 int = '\u03B2'
var ch3 int = '\U00101234'
fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) // integer
fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) // character
fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) // UTF-8 bytes
fmt.Printf("%U - %U - %U", ch, ch2, ch3)   // UTF-8 code point


相关文章
|
2月前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
95 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
2月前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
48 7
|
2月前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
4天前
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
52 20
|
2天前
|
存储 监控 算法
探秘员工泄密行为防线:基于Go语言的布隆过滤器算法解析
在信息爆炸时代,员工泄密行为对企业构成重大威胁。本文聚焦布隆过滤器(Bloom Filter)这一高效数据结构,结合Go语言实现算法,帮助企业识别和预防泄密风险。通过构建正常操作“指纹库”,实时监测员工操作,快速筛查可疑行为。示例代码展示了如何利用布隆过滤器检测异常操作,并提出优化建议,如调整参数、结合日志分析系统等,全方位筑牢企业信息安全防线,守护核心竞争力。
|
10天前
|
Go C语言
Go语言入门:分支结构
本文介绍了Go语言中的条件语句,包括`if...else`、`if...else if`和`switch`结构,并通过多个练习详细解释了它们的用法。`if...else`用于简单的条件判断;`if...else if`处理多条件分支;`switch`则适用于基于不同值的选择逻辑。特别地,文章还介绍了`fallthrough`关键字,用于优化重复代码。通过实例如判断年龄、奇偶数、公交乘车及成绩等级等,帮助读者更好地理解和应用这些结构。
34 14
|
2月前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
124 71
|
2月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
121 67
|
25天前
|
存储 监控 算法
内网监控系统之 Go 语言布隆过滤器算法深度剖析
在数字化时代,内网监控系统对企业和组织的信息安全至关重要。布隆过滤器(Bloom Filter)作为一种高效的数据结构,能够快速判断元素是否存在于集合中,适用于内网监控中的恶意IP和违规域名筛选。本文介绍其原理、优势及Go语言实现,提升系统性能与响应速度,保障信息安全。
28 5
|
1月前
|
算法 安全 Go
Go语言中的加密和解密是如何实现的?
Go语言通过标准库中的`crypto`包提供丰富的加密和解密功能,包括对称加密(如AES)、非对称加密(如RSA、ECDSA)及散列函数(如SHA256)。`encoding/base64`包则用于Base64编码与解码。开发者可根据需求选择合适的算法和密钥,使用这些包进行加密操作。示例代码展示了如何使用`crypto/aes`包实现对称加密。加密和解密操作涉及敏感数据处理,需格外注意安全性。
46 14