文章目录
go 数据类型
一、基本数据类型
整型
有符号整形数类型:
int8,长度:1字节, 取值范围:(-128 ~ 127)
int16,长度:2字节,取值范围:(-32768 ~ 32767)
int32,长度:4字节,取值范围:(-2,147,483,648 ~ 2,147,483,647)
int64.长度:8字节,取值范围:(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)
无符号整形数类型:
uint8,长度:1字节, 取值范围:(0 ~ 255)
uint16,长度:2字节,取值范围:(0 ~ 65535)
uint32,长度:4字节,取值范围:(0 ~ 4,294,967,295)
uint64.长度:8字节,取值范围:(0 ~ 18,446,744,073,709,551,615)
浮点型
浮点型。float32 精确到小数点后 7 位,float64 精确到小数点后 15 位。由于精确度的缘故,你在使用
==
或者
!=
来比较浮点数时应当非常小心。
浮点型(IEEE-754 标准):
float32:(+- 1e-45 -> +- 3.4 * 1e38)32位浮点类型
float64:(+- 5 1e-324 -> 107 1e308)64位浮点类型
浮点型中指数部分由”E”或”e”以及带正负号的10进制整数表示。例:
3.9E-2
表示浮点数
0.039
。
3.9E+1
表示浮点数39。 有时候浮点数类型值也可以被简化。比如39.0可以被简化为39。0.039可以被简化为.039。在Golang中浮点数的相关部分只能由10进制表示法表示
复数
复数类型:
complex64: 由两个float32类型的值分别表示复数的实数部分和虚数部分
complex128: 由两个float64类型的值表示复数的实数部分和虚数部分
复数类型的值一般由浮点数表示的实数部分、加号”+”、浮点数表示的虚数部分以及小写字母”i”组成,例如:
var x complex128 = complex(1,2) //1+2i
对于一个复数 c = complex(x, y) ,可以通过Go语言内置函数 real(z) 获得该复数的实 部,也就是 x ,通过 imag© 获得该复数的虚部,也就是 y
布尔型
在Go语言中,布尔值的类型为 bool,值是 true 或 false,布尔可以做3种逻辑运算,&&(逻辑且),||(逻辑或),!(逻辑非),布尔类型的值不支持其他类型的转换.
布尔值可以和&&(AND)和||(OR)操作符结合,并且可能会有短路行为:如果运算符左边值已经可以确定整个布尔表达式的值,那么运算符右边的值将不在被求值,
字符串
字符串是不可变的字节序列,它可以包含任意数据,包括0值字节,但是主要还是为了人可读的文本。内置的 len()函数返回字符串的字节数
二、复合数据类型
数组
数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。由于数组的长度是固定的,因而在使用的时候我们用的最多的是slice(切片),它是可以增长和收缩动态序列,slice功能也更灵活,但是要理解slice工作原理的话需要先理解数组
申明数组
var variable_name [SIZE] variable_type
var balance [10] float32
初始化数组
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
通过字面量在声明数组的同时快速初始化数组
balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
果数组长度不确定,可以使用
…
代替数组的长度,编译器会根据元素个数自行推断数组的长度
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
如果设置了数组的长度,我们还可以通过指定下标来初始化元素
// 将索引为 1 和 3 的元素初始化
balance := [5]float32{1:2.0,3:7.0}
Slice
Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。一个slice类型一般写作[]T,其中T代表slice中元素的类型;slice的语法和数组很像,只是没有固定长度而已
切片初始化-基于数组
arrVar := [4]int{1, 2, 3, 4}
s1 := arrVar[1:3] //s := arr[startIndex:endIndex] 将 arr 中从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片
s2 := arrVar[1:] //s := arr[startIndex:] 默认 endIndex 时将表示一直到arr的最后一个元素
s3 := arrVar[:2] //s := arr[:endIndex] 默认 startIndex 时将表示从 arr 的第一个元素开始
fmt.Println(s1) //输出结果[2 3]
fmt.Println(s2) //输出结果[2 3 4]
fmt.Println(s3) //输出结果[1 2]
总结:[start:end] 左边包括,右边不包括
切片初始化-直接创建
func main() {
var numbers = make([]int, 3, 5)
printSlice(numbers)
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}
//输出结果 len=3 cap=5 slice=[0 0 0]
和数组不同的是, slice之间不能比较,因此我们不能使用==操作符来判断两个slice是否含有全部相等元素。不过标准库提供了高度优化的bytes.Equal函数来判断两个字节型slice是否相等([]byte),但是对于其他类型的slice,我们必须自己展开每个元素进行比较:
func equal(x, y []string) bool {
if len(x) != len(y) {
return false
}
for i := range x {
if x[i] != y[i] {
return false
}
}
return true
}
Map
Map是一个无序的key/value对集合,其中所有的key都不是相同,然后根据key找到对应的value进行检索、更新或者删除。
Map声明
var m map[string] string
创建
// 创建一个空的 Map
m1 := make(map[string]int)
// 创建一个初始容量为 10 的 Map
m2 := make(map[string]int, 10)
m := map[string]int{
"keke": 001,
"jame": 002,
}
//等价于
m := make(map[string]int)
m["keke"] = 001
m["jame"] = 002
案例
package main
import "fmt"
func main() {
//初始化map
m := map[string]string{
"name": "lisi",
"age": "15",
"address": "wuhan",
}
//根据key获取元素
v1 := m["name"]
fmt.Println("根据key获取元素:" + v1)
//修改键值对
m["age"] = "17"
v2 := m["age"]
fmt.Println("修改键值对:" + v2)
//获取 Map 的长度
len := len(m)
fmt.Println("获取 Map 的长度:", len)
//添加键值对
fmt.Println("添加键值对============")
m["sex"] = "男"
//遍历 Map:
for key := range m {
fmt.Println(key, "-", m[key])
}
//判断元素是否存在
//ok := m["name"]
name, ok := m["address"]
if ok {
fmt.Println("地址是", name)
} else {
fmt.Println("地址不存在")
}
fmt.Println(ok)
//删除元素
delete(m, "sex")
fmt.Println("删除之后=============")
for key := range m {
fmt.Println(key, "-", m[key])
}
}
执行结果:
根据key获取元素:lisi
修改键值对:17
获取 Map 的长度: 3
添加键值对============
name - lisi
age - 17
address - wuhan
sex - 男
地址是 wuhan
true
删除之后=============
address - wuhan
name - lisi
age - 17
结构体
Go提供的结构体就是把使用各种数据类型定义的不同变量组合起来的高级数据类型
定义结构体
type User struct {
name string
age int
address string
weight float32
}
案例
package main
import "fmt"
func main() {
user := User{name: "zhangsan", age: 18, address: "wuhan", weight: 100.57}
user1 := User{"lisi", 28, "beijing", 99.86}
fmt.Println(user)
fmt.Println(user1)
}
type User struct {
name string
age int
address string
weight float32
}
输出结果:
{zhangsan 18 wuhan 100.57}
{lisi 28 beijing 99.86}
访问结构体成员
如果要访问结构体成员,需要使用点号
.
操作符,格式为:
结构体.成员名
案例
package main
import "fmt"
func main() {
user := User{name: "zhangsan", age: 18, address: "wuhan", weight: 100.57}
fmt.Println("张三用户", user)
//赋值
var user1 User
user1.name = "lisi"
user1.age = 28
user1.weight = 88.88
fmt.Println("李四用户", user1)
//获取值
address := user.address
fmt.Println("用户张三家的地址为", address)
}
type User struct {
name string
age int
address string
weight float32
}
输出结果
张三用户 {zhangsan 18 wuhan 100.57}
李四用户 {lisi 28 88.88}
用户张三家的地址为 wuhan
结构体作为函数参数
案例
package main
import "fmt"
func main() {
user := User{name: "zhangsan", age: 18, address: "wuhan", weight: 100.57}
printUser(user)
}
func printUser(user User) {
fmt.Printf("user name : %s\n", user.name)
fmt.Printf("user age : %d\n", user.age)
fmt.Printf("user address : %s\n", user.address)
fmt.Printf("user weight : %v\n", user.weight)
}
type User struct {
name string
age int
address string
weight float32
}
输出结果
user name : zhangsan
user age : 18
user address : wuhan
user weight : 100.57
结构体指针
你可以定义指向结构体的指针类似于其他指针变量,格式如下:
var struct_pointer *Books
以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:
struct_pointer = &Book1
使用结构体指针访问结构体成员,使用 “.” 操作符:
结构体名称.属性
案例
package main
import "fmt"
func main() {
var r = new(Rectangle)
r.width = 100
r.length = 200
fmt.Println("Width:", r.width, "Length:", r.length, "Area:", r.area())
fmt.Println("Width:", r.width, "Length:", r.length, "Area:", r.double_area())
}
func (r Rectangle) area() float64 {
return r.width * r.length
}
func (r *Rectangle) double_area() float64 {
r.width *= 2
r.length *= 2
return r.width * r.length
}
type Rectangle struct {
width float64
length float64
}
输出结果
Width: 100 Length: 200 Area: 20000
Width: 200 Length: 400 Area: 80000
其实使不使用指针,取决于你是否试图在函数内部改变传递进来的参数的值
结构体特性
- 如果结构体成员名字是以大写字母开头的,在其他包中可以进行读写结构体字段名以小写字母开头是当前包的私有的,函数定义也是类似的
- 一个命名为S的结构体类型将不能再包含S类型的成员,但是S类型的结构体可以包含*S指针类型的成员,这可以让我们创建递归的数据结构,比如链表和树结构等
结构体嵌入
package main
import "fmt"
func main() {
var w Wheel
w.Circle.Center.X = 8
w.Circle.Center.Y = 8
w.Circle.Radius = 5
w.Spokes = 20
fmt.Println(w)
}
type Point struct {
X, Y int
}
type Circle struct {
Center Point
Radius int
}
type Wheel struct {
Circle Circle
Spokes int
}
输出结果
{{{8 8} 5} 20}
匿名函数
Go语言有一个特性让我们只声明一个成员对应的数据类型而不指名成员的名字;这类成员就叫匿名成员。匿名成员的数据类型必须是命名的类型或指向一个命名的类型的指针。下面的代码中,Circle和Wheel各自都有一个匿名成员。我们可以说Point类型被嵌入到了Circle结构体,同时Circle类型被嵌入到了Wheel结构体
package main
import "fmt"
func main() {
var w Wheel
w.X = 8 // w.Circle.Point.X = 8
w.Y = 8 // w.Circle.Point.Y = 8
w.Radius = 5 // w.Circle.Radius = 5
w.Spokes = 20
fmt.Println(w)
}
type Point struct {
X, Y int
}
type Circle struct {
Point // 匿名字段,struct
Radius int
}
type Wheel struct {
Circle // 匿名字段,struct
Spokes int
}
输出结果
{{{8 8} 5} 20}