[TOC] ## 整数 ## 数字类型 1. 无符号整型 ``` uint8 //1 个字节 0-255 uint16 //2 个字节 0-65535 uint32 //3 个字节 0-4294967295 uint64 //3 个字节 0-18446744073709551615 ``` 2. 有符号整型 ``` int8 //1 个字节 -128-127 int16 //2 个字节 -32768-32767 int32 //3 个字节 -2147483648-2147483647 int64 //3 个字节 -9223372036854775808-9223372036854775807 ``` ## 浮点型 ``` float32 //32位浮点型数 float64 //64位浮点型数 complex64 //32 位实数和虚数 complex128 //64 位实数和虚数 ``` ## 其他数字类型 ``` byte //uint8 rune //int32 uint //32 或 64 位 根据系统决定 int //与 uint 一样大小 uintptr //无符号整型,用于存放一个指针 ``` ## 指针类型( Pointer) ### 指针赋值 ``` var a = 3 var p = &a //取内存值 *p = 4 fmt.Println(a) //0xc042052080 fmt.Println(p) //4 ``` ### 指针传参 ``` func swap(a *int) { *a++ } a := 3 swap(&a) fmt.Println(a) //4 ``` ## 数组类型 (在 go 语言中一般不使用数组,推荐切片) ``` //初始化赋值 var a[5] a[0]=12 var 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} //多维数组 b :=[][]int { {1,2,3}, {3,24,35}, {11,22,33}, } ``` ## 字符串类型 ``` 如 str :="abc" a :=[]tybe(str) 原str 字符串的值是不能改变 转成[]tybe 变为更灵活的切片类型 ``` ## 切片类型( slice) 1.切片的创建方式 基于底层数组创建,直接创建,或者 make() 函数创建 1. 与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。 1. len() 方法获取长度。 3. 添加切片 `append` 与拷贝切片 `copy` ``` //创建 a :=[]int {10,20,30,40,50,60,70} b :=a[1:3] //{20,30} c :=a[1:] //{20,30,40,50,60,70} d :=a[:3] //{10,20,30} //添加贴片 var numbers =[]int{1,2,3} /* 允许追加空切片 */ numbers = append(numbers, 3) fmt.Println(numbers) //[1 2 3 3] /* 拷贝 numbers 的内容到 numbers1 */ copy(numbers1,numbers) //len=3 cap=8 slice=[0 1 2] ``` > 区别 ``` a :=[]int{1,2,3} //切片 b :=[...]int{1,2,3} //数组 c :=b[:] //从数组中生成切片 fmt.Println(reflect.TypeOf(a))//[]int fmt.Println(reflect.TypeOf(b)) //[3]int fmt.Println(reflect.TypeOf(c)) //[]int -切片 值为[1 2 3] ``` ### make([]int) 指定的长度根据真实长度扩展 ``` a := make([]int, 2, 3) fmt.Println(len(a)) //2 fmt.Println(cap(a)) //3 a = append(a, 2, 2, 2) fmt.Println(len(a)) //5 fmt.Println(cap(a)) //6 ``` ## 结构化类型(struct) ``` type Books struct { title string author string subject string book_id int } ``` ## Channe|类型(chan) 不能超过设置的长度 ``` person := make(chan int) 默认的长度只有1,超出后报错 person <- 12 person <- 23 //fatal error: all goroutines are asleep - deadlock! ``` ## 函数类型(func) ``` //int 类型也可改为 a ...interface{} 传 demo(3,4,"5") func demo(a ...int){ fmt.Print(a) //[3 4 5] } demo(3,4,5) ``` ### 复杂传值 ``` func demo(a ...interface{}){ fmt.Print(a) //[3 4 5 [3 4 5]] } a :=[]interface{}{3,4,5} demo(3,4,5,a) ``` ### 函数参数为数组时的长度需相等 ``` func demo(a [5]int){ fmt.Println(a) } //ok a :=[5]int{1,2,3,4,5} demo(a) //error a :=[3]int{1,2,3} demo(a) ``` ### 函数当作参数传值 ``` func compute(fn func(int, int) int) int { return fn(3, 4) } func main() { c := compute(add) fmt.Println(c) } func add(a, b int) int { return a + b } ``` ### 闭包函数 - 实现斐波那契数组 函数返回前的变量不会改变 ``` func fibonacci1() func() int { back1, back2 := 0, 1 // 该值初始化一次,return 中把 back1,back2的变化会保留下来 return func() int { temp := back1 back1, back2 = back2, (back1 + back2) //返回temp return temp } } func main() { f := fibonacci1() // for i := 0; i < 10; i++ { // 检测下前10个值 fmt.Println(f()) } } ``` ## 接口实现 ### 接口与隐式实现 无需声明某个结构体实现了接口,当结构体满足接口时,即完成了接口的实现 ``` type I interface { M() } type T struct { S string } // 此方法表示类型 T 实现了接口 I,但我们无需显式声明此事。 func (t T) M() { fmt.Println(t.S) } ``` ### 空接口( interface) - 指定了零个方法的接口值 创建符合接口的结构体 ``` //定义phone的接口必须要有call type Phone interface { call() } //构建结构体 type NokiaPhone struct { } func (nokiaPhone NokiaPhone) call() { fmt.Println("I am Nokia, I can call you!") } func main() { var phone Phone phone = new(NokiaPhone) //接头体传入接口 如果不存在call() 则new 会保存 phone.call() fmt.Println(reflect.TypeOf(phone)) } ``` ### interface 可以当任何值 ``` // 定义a为空接口 var a interface{} var i int = 5 s := "Hello world" // a可以存储任意类型的数值 a = i a = s ``` ### interface变量存储的类型 可以直接判断是否是该类型的变量:` value, ok = element.(T)`,这里value就是变量的值,ok是一个bool类型,element是interface变量,T是断言的类型。 ``` ype Element interface {} type List [] Element type Person struct { name string age int } func main() { list := make(List,3) list[0] = 1 // an int list[1] = "Hello" // a string list[2] = Person{"Dennis", 70} for index, element := range list { if value, ok := element.(int); ok { fmt.Printf("list[%d] is an int and its value is %d\n", index, value) } else if value, ok := element.(string); ok { fmt.Printf("list[%d] is a string and its value is %s\n", index, value) } else if value, ok := element.(Person); ok { fmt.Printf("list[%d] is a Person and its value is %s\n", index, value) } else { fmt.Printf("list[%d] is of a different type\n", index) } } } ``` ## Map类型(map) 1. 初始化并赋值 ``` var countryCapitalMap map[string]string /*创建集合 */ countryCapitalMap = make(map[string]string) ``` 等同于 ``` countryCapitalMap := make(map[string]string) ``` 2. 删除 ``` countryCapitalMap := make(map[string]string) countryCapitalMap [ "France" ] = "Paris" //删除 delete(countryCapitalMap, "France") ``` 3. 存在键判断键是否 ``` elem, ok = m[key] ``` ## 反射 ``` t := reflect.TypeOf(i) //得到类型的元数据,通过t我们能获取类型定义里面的所有元素 v := reflect.ValueOf(i) //得到实际的值,通过v我们获取存储在里面的值,还可以去改变值 ``` ## 类型断言 1. 使用 switch 断言 ``` var a interface{} a = 123.1 switch value := a.(type) { case int: fmt.Printf("int : %v", value) case float64: fmt.Printf("float : %v", value) case string: fmt.Printf("string : %v", value) case bool: fmt.Printf("bool : %v", value) default: fmt.Printf("not found") } ``` 2. 使用反射 (推荐) ``` a = 123.1 of := reflect.TypeOf(a) fmt.Println(of) //float64 ``` ## 特殊常量iota概念 ``` const A = iota //0 const ( C=iota //0 D=iota //1 ) ``` 1. iota在 const关键字出现时将被重置为0; 2. const中每新增一行常量声明将使iota计数一次; 3. iota常见使用法 1 跳值使用法 ``` const ( C=iota //0 D=iota //1 _ E =iota //3 ) ``` 2 插队使用法 ``` const ( C=iota //0 D=iota //1 B="asd" E =iota //3 ) ``` 3 表达式隐式使用法 ``` const ( C=iota*2 //0 D //1*2=2 B //2*2=4 ) ``` 使用空表达式时,会找最近非空表达式 4 单行使用法 ``` const ( A,B=iota,iota*3 //A=0 B=0 C,D //C=1 D=3 ) ```