Go基础-数据类型
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) }