Go语言中有丰富的数据类型,除了基本的整型、浮点型、布尔型、字符串外,还有数组、切片、结构体、函数、map、通道(channel)等。
整型 int
//int8 int16 int32 int64 有符号 -
//uint8 无符号
//int 类型会根据系统指定位数,32位是int32,64位是int64
func main() {
//十进制
i1 := 10
fmt.Printf("%d\n", i1) //十进制
fmt.Printf("%b\n", i1) //转换为二进制
fmt.Printf("%o\n", i1) //转换为八进制
fmt.Printf("%x\n", i1) //转换为十六进制
fmt.Printf("%T\n", i1) //查看int类型
}
浮点型 float
//默认浮点数是float64类型
//类型不同不可以直接赋值,需要做类型转换
func main() {
fmt.Println(math.MaxFloat32)
fmt.Printf("%f\n", math.Pi)
fmt.Printf("%.2f\n", math.Pi)
f1 := 1.2344
fmt.Printf("%T\n", f1)
f2 := float32(1.1234)
fmt.Printf("%T\n", f2)
f2 = float32(f1)
fmt.Println(f2)
}
布尔值 bool
import "fmt"
var isOk bool
//bool值默认为false
//bool值和其他类型无法转换
func main() {
fmt.Println(isOk)
}
字符串 string
import (
"fmt"
"strings"
)
func main() {
// \转义 在" "里面的单引号不需要转义
s1 := "E:\\goproject\\src\\github.com\\day01"
fmt.Println(s1)
// 多行定义
s2 := `
一壶清茶
绿新芽
`
fmt.Println(s2)
// 字符串常用操作
// len() 求长度
s3 := "十里烟霞 如今谁画 销魂挂" //11*3+2
fmt.Println(len(s3))
s4 := "i love my doctor"
fmt.Println(len(s4))
// + 拼接字符串
fmt.Println(s3 + s4)
fmt.Printf("%v%v\n", s3, s4)
s5 := fmt.Sprintf("%s%s", s3, s4)
fmt.Printf(s5)
// 分割字符串
s6 := strings.Split(s3, " ")
fmt.Printf("%T\n", s6)
fmt.Println(s6)
// 包含
fmt.Println(strings.Contains(s3, "十里"))
// 前缀判断
fmt.Println(strings.HasPrefix(s3, "八"))
// 后缀判断
fmt.Println(strings.HasSuffix(s3, "销魂挂"))
// 字符出现的位置
s7 := "abcdeb"
fmt.Println(strings.Index(s7, "c")) //第一次出现
// 最后一次出现的位置
fmt.Println(strings.LastIndex(s7, "b"))
// 字符串链接 前面是一个切片
fmt.Println(strings.Join(s6, ","))
}
数组
func main() {
//1: 数组必须指定存放的容量和类型
arr := [3]string{"上海", "北京", "深圳"}
//2:...可以根据数组的长度自己推断
arr1 := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
//3:根据索引初始化
arr2 := [5]int{0: 2, 3: 5}
fmt.Println(arr, arr1, arr2)
//遍历数组
// 1: 索引遍历
for i := 0; i < len(arr); i++ {
fmt.Println(arr[i])
}
// 2: range遍历
for i, v := range arr {
// i 是索引,v是值
fmt.Println(i, v)
}
//多维数组
var arr3 [3][2]int
arr3 = [3][2]int{
{1, 2},
{3, 4},
{5, 6},
}
fmt.Println(arr3)
//多维数组的遍历
for _, v1 := range arr3 {
fmt.Println(v1)
for _, v2 := range v1 {
fmt.Println(v2)
}
}
//数组是值类型
b1 := [2]int{1, 2} //[1,2]
b2 := b1 //[1,2]
b2[0] = 0 //[0,2]
fmt.Println(b1, b2) //[1,2][0,2]
}
切片
import "fmt"
import "sort"
//切片
//1:切片是引用类型
//2:切片的长度是它元素的个数
//3:切片的容量是底层数组从切片的第一个元素到最后一个元素的数量
//4:一个nil值的切片长度和容量都是0,但是一个长度和容量是0的切片不一定是nil。所以判断切片是否为空,要用 len(s) == 0 判断 不要用 s==nil
func main() {
//定义切片
var s []int //定义了一个int类型的切片,注意和数组的区别
s = []int{1, 2, 3}
fmt.Printf("长度:%d 容量:%d\n", len(s), cap(s))
//由数组得到切片
a1 := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := a1[:5] //[1 2 3 4 5] 这里索引到4 注意:左闭右开 还有 [1:5] [1:] [:]
//这里由于切片属于引用类型,容量是从切片位置算起的,注意下面两个的区别
fmt.Println(s1)
fmt.Printf("长度:%d 容量:%d\n", len(s1), cap(s1)) //5,9
s2 := a1[2:7]
fmt.Println(s2)
fmt.Printf("长度:%d 容量:%d\n", len(s2), cap(s2)) //5,7
//使用make函数构造切片 make([]T,size,cap) //T 切片的元素类型 size 数量 cap 容量
s3 := make([]int,3,10)
fmt.Printf("值:%v,长度:%d 容量:%d\n",s3,len(s3),cap(s3))// [0 0 0] 3,10
//append() 追加元素到切片
//此处注意加了 值之后,s4切片的容量从3变为6.说明底层数组扩容为倍数扩容
s4 := []string{"北京","上海","深圳"}
fmt.Printf("值:%v,长度:%d 容量:%d\n",s4,len(s4),cap(s4))
s4 = append(s4,"广州")
fmt.Printf("值:%v,长度:%d 容量:%d\n",s4,len(s4),cap(s4))
s5 := []string{"武汉","长沙","成都"}
s4 = append(s4,s5...) // ... 表示拆开s5
fmt.Printf("值:%v,长度:%d 容量:%d\n",s4,len(s4),cap(s4))
//copy(new,old) 复制切片
//由于切片是引用类型,所以直接用复制的方式是指向同一个地址,copy可以重新申明成一个新的。注意这里的新切片申明需要make,如果是var没有内存是copy不进去的。
s6 := []int{1,2,3}
s7 := s6
s8 := make([]int,3,3)
copy(s8,s6)
s6[2] = 30
fmt.Printf("s6值:%v,长度:%d 容量:%d\n",s6,len(s6),cap(s6))
fmt.Printf("s7值:%v,长度:%d 容量:%d\n",s7,len(s7),cap(s7))
fmt.Printf("s8值:%v,长度:%d 容量:%d\n",s8,len(s8),cap(s8))
//切片没有删除函数 可以使用append
s8 = append(s8[:1],s8[2:]...)
fmt.Println(s8)
//排序 这里要引用sort包
s9 := []int{1,3,2,7,4}
sort.Ints(s9)
fmt.Println(s9)
}
指针
func main() {
name := "张三"
//&取地址
fmt.Println(&name) // 0xc000048230
//*根据地址取值
p := &name
fmt.Println(*p) // 张三
// 此方式出来的结果是nil,不可使用
var p1 *int
fmt.Println(p1) // nil
// new 函数申请内存地址
var p2 = new(int)
fmt.Println(p2) // 0xc0000aa090
//make和new都是申请内存的
//new给基本数据申请内存 int string,返回的是对应类型的指针 *int *string
//make给slice,map,chan申请,由于他们是引用类型,返回的是类型本身
}
map
//map 引用类型
func main() {
// var m1 map[int]string //这样没有初始化 属于nil
m1 := make(map[int]string) //这里申明可以先预估容量
m1[21] = "张三"
m1[22] = "李四"
fmt.Println(m1)
v, ok := m1[20]
fmt.Println(v, ok) //此处返回对应值和是否存在,不存在int是0,string是""
if !ok {
fmt.Println("无数据")
} else {
fmt.Println(v)
}
// 遍历
for k, v := range m1 {
fmt.Println(k, v)
}
// delete(map key)删除
delete(m1, 21)
fmt.Println(m1)
}
结构体
package main
import "fmt"
//自定义类型和类型别名:基于一个基础类型自定义
type myInt int //自定义类型
type it = int //类型别名
//结构体 类似model
type person struct {
name string
age int
}
//修改年龄
func updateAge(p person) {
p.age = 21
}
func updateAge1(p *person) {
p.age = 22
}
//模拟构造函数
//结构体是值类型
//当结构体比较大的时候尽量使用结构体指针,减少程序内存开销
func newPerson(name string, age int) person {
return person{
name: name,
age: age,
}
}
func main() {
var n myInt
n = 100
fmt.Printf("%T\n", n) //main.myInt类型
var n1 it
n1 = 200
fmt.Printf("%T\n", n1) // int类型 rune就是int32的别名
var p person
p.name = "张三"
p.age = 20
fmt.Println(p)
updateAge(p)
fmt.Println(p.age) //由于go函数传参是拷贝副本,所以此处不是21 还是20
updateAge1(&p)
fmt.Println(p.age) // 这里传过去的是内存地址,所以这里结果是22
//匿名结构体
var stu struct {
address string
code string
}
stu.address = "南京路"
stu.code = "20000"
fmt.Println(stu.address, stu.code)
//调用构造函数
p1 := newPerson("李四", 30)
fmt.Println(p1)
}