类型 #### 常见类型 ======== 变量声明:: var v1 int var v2 string var v3 [] int // 数组 var v4 []int // 数组切片 var v5 struct { f int } var v6 *int // 指针 var v7 map[string]int //map类型: key为string类型,value为int类型 var v8 func(a int) int var ( vv1 int vv2 string ) 常量定义:: const Pi float64 = 3.141592653589793 const zero = 0.0 // 无类型浮点常量 const ( size int64 =1024 eof = -1 // 无类型整形常量 ) const u, v float32 = 0, 3 // u=0.0, v=3.0 常量的多重赋值 const a, b, c = 3, 4, "float" //a=3, b=4, c="float", 无类型整形和字符串常量 预定义:: true, false, iota iota: 每个const出现是重置为0, 这期间每次iota, 其代表的数字都会+1 const ( c0 = iota // iota:0, c0: 0 c1 = iota // iota:1, c1: 1 c2 = 1 << iota // iota:2, c2: 4 c3 = 2 * iota // iota:3, c3: 6 ) 枚举:: const ( Sunday = iota // 0 Monday // 1 Tuesday // 2 thursday // 此变量没导出 ) 类型 ==== 1. 基础类型(值传递):: 布尔: bool 整形: int8, byte(uint8), int16, int(长度平台相关), uint, uintptr 浮点: float32, float64 复数: complex64, complex128 字符串: string 字符: rune //代表unicode字符,bype代表utf8字符 错误类型: error 数组: array 2. 引用类型(指针传递):: 切片: slice 字典: map 通道: chan 4. 结构体类型(struct):: type person struct { age int // 值传递 name []string // 指针传递 } 5. 自定义类型:: type A int64 type B int64 // Go这种强类型语言,A和B是不能相互赋值的 3. 其他类型:: 接口: interface 函数类型 指针: pointer 嵌入类型-或者嵌套类型 ===================== 接口类型嵌入:: 这是一种可以把已有的类型声明在新的类型里的一种方式,这种功能对代码复用非常重要 type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) } type ReadWriter interface { Reader Writer } 结构体类型嵌入:: type user struct { name string email string } type admin struct { user // 嵌入 level string } 重点几个数据类型 ================ 位运算:: x << y 左移 x >> y 右移 x ^ y 异或 x & y 与 x | y 或 ^x 取反(c中为~c) chan类型:: one := make(chan int) // 无缓冲的通道 ch := make(chan int, 3) // 有缓冲的通道 // 单向通道 var send chan<- int //只能发送 var receive <-chan int //只能接收 struct结构:: type G struct { H int I string } type T struct{ A bool B int "myb" // go struct tag(用来辅助反射的):: D string `bson:",omitempty"json:"jsonkey"` G //匿名字段,那么默认T就包含了G的所有字段,即: H, I } // 使用: t := T { false, "myb", "bson", G{1, "iii"} } fmt.Println(t.H) // 1 访问结构G的字段H就像访问自己的字段一样 map数据类型:: 1. 元素声明: var a map[string] PersonInfo var b map[string] int 2. 创建并初使化map代码如下: a := map[string] PeronsInfo { "1234" : PersonInfo{"1", "gordon"} } b := map[string]int{} 3. 元素赋值: a["key"] = PersonInfo{"12", "gordon"} b["key"] = 1 4. 元素删除: delete(a, "key") // 如传入的key不存在,则不做任何操作; 如key为nil则抛异常 5. 元素查找: value, ok := myMap["key"] if ok { // 找到了 } else { // 没找到 } Map是给予散列表来实现,就是我们常说的Hash表 Map的散列表包含一组桶,每次存储和查找键值对的时候,都要先选择一个桶 存储的数据越多,索引分布越均匀,所以我们访问键值对的速度也就越快 注: Map存储的是无序的键值对集合 Map的创建有make函数 dict:=make(map[string]int) 指针类型:: 为了安全的考虑,Go语言是不允许两个指针类型进行转换 两个不同的指针类型不能相互转换,比如*int不能转为*float64 unsafe.Pointer是一种特殊意义的指针,它可以包含任意类型的地址,有点类似于C语言里的void*指针,全能型的 unsafe.Pointer的4个规则: 1. 任何指针都可以转换为unsafe.Pointer 2. unsafe.Pointer可以转换为任何指针 3. uintptr可以转换为unsafe.Pointer 4. unsafe.Pointer可以转换为uintptr 流程控制:: 条件语句: if, else, else if 选择语句: switch, case, select 循环语句: for, range 跳转语句: goto 函数(function):: 1. 函数组成: func, 函数名, 参数列表, 返回值, 函数体, 返回语句 2. 不定参数: func myfunc(args ...int) 2.1 不定参数传递: func myfunc(args ...int) { // 原样传递 myfunc3(args...) // 传递片段 myfunc3(args[1:]...) } 2.2 任意类型的不定参数 // 如果你想传任意类型,可指定类型为interface{} func Print(format string, args ...interface{}) { } 3. 多返回值(如果对某一值不关心可以使用“_”代替) file, _ := os.Open("/usr/tmp") 4. 匿名函数: f := func(x, y int) int { return x+y } // {}后直接跟参数列表表示函数调用 func(ch chan int) { ch <- ACK }(reply_chan) 5. 闭包: 方法(method):: 注意: 在golang中方法与函数是不相同的 函数是指不属于任何结构体、类型的方法 也就是说,函数是没有接收者的;而方法是有接收者的,要么是属于一个结构体的,要么属于一个新定义的类型的 如: type person struct { name string } func (p person) String() string{ return "the person name is "+p.name } 接口:: 抽象就是接口的优势,它不用和具体的实现细节绑定在一起,我们只需定义接口,告诉编码人员它可以做什么, 这样我们可以把具体实现分开,这样编码就会更加灵活方面,适应能力也会非常强 错误处理:: 1. error接口 type error interface { Error() string } // 如果要返回error, 将error作为多返回值的最后一个: func foo(param int)(n int, error error) { } // 使用: n, err := foo(0) if err != nil { //有错误的情况 } 2. defer 调用遵照先进后出的原则 3. panic() func panic(interface{}) 当一个函数调用panic()时,正常执行流程将立即终止 之后就会走defer流程 4. recover() func recover() interface{} recover()用于终止错误处理流程 一般会在defer中设定,便于处理panic产生的错误 反射(还需要进行详细了解@todo):: t := reflect.TypeOf(i) //得到类型的元数据,通过t我们能获取类型定义里面的所有元素 v := reflect.ValueOf(i) //得到实际的值,通过v我们获取存储在里面的值,还可以去改变值 tag := t.Elem().Field(0).Tag //获取定义在struct里面的标签 name := v.Elem().Field(0).String() //获取存储在第一个字段里面的值 并发相关 ======== :: ch := make(chan type, value) //value == 0 ! 无缓冲(阻塞) //value > 0 ! 缓冲(非阻塞,直到value 个元素) //技巧: 使用range c := make(chan int, 10) for i:= range c { fmt.Println(i) } //技巧:使用select, 超时与default(伪代码) select { case v := <-c: println(v) case <- time.After(5 * time.Second): // 因为有default,所以永远不会执行到这儿 println("time out") break default: println("default") } // runtime包几个处理goroutine的函数 Goexit: 退出当前执行的goroutine,但是defer函数还会继续调用 Gosched: 让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行 NumCPU: 返回 CPU 核数量 NumGoroutine: 返回正在执行和排队的任务总数 GOMAXPROCS: 用来设置可以并行计算的CPU核数的最大值,并返回之前的值 源码 ==== 最底层的类型:: const ( Invalid Kind = iota Bool Int Int8 Int16 Int32 Int64 Uint Uint8 Uint16 Uint32 Uint64 Uintptr Float32 Float64 Complex64 Complex128 Array Chan Func Interface Map Ptr Slice String Struct UnsafePointer )