整数
有符号整数
int8 int16 int32 int64
无符号整数
uin8 uin16 uin32 uin64
无符号整数 uintptr可以进行运算这点很重要请了解unsafe包,大小不明确,足以完整存放指针,uinptr只用于底层编程。
rune 类型是int32的同义词,常常用于指明一个值是unicode码点。
a:="这是golang"
for i:=0;i< len(a);i++ {
fmt.Println(a[i])
}
输出:
232
191
153
230
152
175
103
111
108
97
110
103
这是按utf8码点输出的
但是如果将a变为rune类型
package main
import "fmt"
func main(){
a:=[]rune("这是golang")
for i:=0;i< len(a);i++ {
fmt.Println(a[i])
}
}
输出:
36825
26159
103
111
108
97
110
103
按照unicode码点序列输出
常量
在编译阶段就计算出表达式的值,意义在程序运行过程中防止恶意篡改。
声明常量使用关键字const
如:const e = 1234141241(也可以指定类型当然何必多此一举?)
常量声明不需要写type,会根据右边表达式类型自动推导。
常量生成器iota 就是枚举。
逻辑运算符
&&、||、!
浮点数
float32 float64
布尔
true false
字符串
原始字符串字面量`........`
字符串和字节切片转换
字符串可以使用切片的索引方式。
常用内置函数
append
len
cap
make
new
delete
close
panic
recover
数组
具有固定长度拥有零个或多个相同类型的元素序列
var a [3]int
var b [3]int = [3]int{1,2,3}
数组长度是数组类型的一部分。[2]int [3]int是不同类型的数组。
c := [...]int{99:-1} 这个数组有100个元素其中第100个元素的值-1其他元素均为类型零值。
go语言中数组是按值传递。
切片slice
slice是一种轻量级数据结构,
type lisce struct{
data ptr //指针
len int //实际长度
cap int //容量
}
一个底层数组可以对应多个slice 并且可以相互重叠。
切片索引方[m:n]返回一个原切片类型的一个切片
slice无法做比较因为同一个slice在同一时间可能拥有不同的值。
slice只可以和nil比较,但是slice==nil不代表slice为空,还是要通过len(slice)==0判断是否为空
切片可以包含多个子切片并且当子切片一直被引用那么原切片就不会被垃圾回收如下:
func main(){
b := ftest()
fmt.Println(b)
}
func ftest()[]int{
a := []int{1,2,3,4,5,6,7,8,8,9,123,1,234,5,34,56,7}
return a[1:3]
}
上面的代码切片a一直被引用到程序结束。改正方法如下:
func ftest()[]int{
a := []int{1,2,3,4,5,6,7,8,8,9,123,1,234,5,34,56,7}
c := make([]int,2)
c = a[1:3]
return c
}
map
散列表所有的键、值都拥有相同的数据类型
a:=make(map[string]int)
map不是一个变量不可以获取地址,因为map的增长可能导致已有元素重新分配新的位置使得获取的地址无效。
map迭代顺序不固定,不同的实现方法会使用不用的散列算法
map只可以和nil比较
如果散列表的value是结构体不能直接对其进行修改会报错。
type a struct{
b int
}
m = make(map[int]a)
v = a{b:1}
m[0] = v
m[0].b = 2 //崩溃
u:=m[0]
u.b = 2
m[0] = u //正确
z=make(map[int]*a)
z[0] = *v
z[0].b++ //正确
结构体
将零个或多个任意类型的命名变量组合在一起的聚合类型。
命名的结构体类型中不可以定义一个拥有相同结构体类型的成员变量,也就是一个聚合类型不可以包含他自己,但是可以包含一个指向相同结构体类型的指针。
结构体的匿名字段
type b struct {
i int
}
type a struct {
i int
b
}
结构体a中存在匿名字段b,此时类型就是字段b的名称,类似于继承。
a结构体的字段总包含b称作b嵌入于a。
结构体中也可以嵌入接口。
当结构体中嵌入多个结构体并且其中有多个结构体的字段重名,那么外层结构体的字段会覆盖内层的结构体字段但是他们的内存空间都保留。比如:
- i 指的是结构体a中的i字段,如果想访问b可以a.b.i来访问
可比较性
如果结构体中所有成员都是可比较多那么这个结构体就是可比较的。
接口
接口即是约定,是一套必须实现的方法集蓝本,要想实现一个接口就要实现这个接口的所有方法。
package io
type Reader interface{
Read(p []byte)(n int,err error)
}
实现 io.Reader 接口
var s []byte
func (str s)(n int,err error){
return len(str),true
}
var r io.Reader = s
接口分为动态接口类型和动态接口值 上式中动态接口类型为[]byte 动态接口值为nil
类型断言
我们经常需要判断一个接口的动态类型,这时需要检测其是否为某一类型。
如果T是一个具体得到类型,写出来类似于x.(T) 检测x的动态类型是否为T,为真则返回x的动态接口值,为假则崩溃。
如果T是一个接口类型在判断动态类型是否满足这个接口。
如果类型断言出现在需要两个结果的表达式则不会崩溃。
f,ok := w.(*os.file)
类型分支类判断接口类型
switch x.(type):
case nil:
case int,uint:
case string:
default: