go 知识点合辑
Go
(u)int(8|16|32|64)、bool、string、uintptr、byte(=uint8)、rune(=uint32)、float[32|64]、complex[64|128]
chan、interface、func
array、slice、map
reserved-keywords:25 package import struct interface const map type func if else for switch select break continue goto return fallthrough case default defer range go chan var 预定义标识符:内嵌函数和数据类型等 append iota len cap make new copy close imag print println panic real recover true false nil
switch case
fallthrough : 强制执行后面的case代码
函数
不支持重载,一个包不能有两个名字一样的函数
命名返回值的名字(return可以不指定变量名)
func add(a, b int) (c int) { c = a + b return }
可变参数
可变参数实际上是一个slice,可以通过arg[index]依次访问所有参数;通过len(arg)来判断变参的个数
func concat(s string, arg ...string) string { str := s for i := 0; i < len(arg); i++ { str += arg[i] } return str }
main & init & defer
Go程序会自动调用init()和main(),所以你不需要在任何地方调用这两个函数
init()可以在任何package中出现(可选); main()只能用在package main 中(必需)
defer
当函数返回时,执行defer语句
多个defer语句,按先进后出的方式执行
defer语句中的变量,在defer声明时确定变量
触发异常也会走defer语句
闭包
闭包是一个函数和与其相关的引用环境组合而成的实体
函数可以存储到变量中作为参数传递给其它函数,能够被函数动态的创建和返回
func Adder() func(int) int { var x int return func(d int) int { x += d return x } } f := Adder() fmt.Println(f(1)) //1 fmt.Println(f(10)) //11 fmt.Println(f(100)) //111
值传递 & 引用传递
无论是值传递,还是引用传递,传递给函数的都是变量的副本; 值传递是值的拷贝,引用传递是地址的拷贝
map、slice、chan、指针、interface默认以引用的方式传递
new 分配内存,主要用来分配值类型,比如int、struct,返回的是指针
make 分配内存,主要用来分配引用类型,比如chan、map、slice
程序初始化与执行过程
程序的初始化和执行都起于main包, 编译时将依赖的包依次导入
如果一个包会被多个包同时导入,那么它只会被导入一次
流程:
包初始化时,会先逐层递归的将它依赖的包导入进来,直到顶层包。
然后对顶层包中的包级常量和变量进行初始化,接着执行init函数(如果有的话),依次类推,直到最外层包被初始化。
等所有被导入的包加载完毕,就开始对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数。
Array & Slice & Map & Struct
Array
数组是值类型,当作为方法的入参传入时将复制一份数组而不是引用同一指针;
Slice
切片是数组的一个容量固定、长度可变的引用,因此切片是引用类型
slice 是一个指向array的指针。在传递切片时,等同于传递了一指针。
slice 可以自动扩容
Map
引用类型
Struct
值类型
range
作用于 string or map,可以返回系列 (key, value)
tag & String() & 类型断言
tag
在转换成其它数据格式的时候,会使用其中特定的字段作为键值
String()
如果Interface实现了String()这个方法,那么fmt中默认会调其用String()
类型断言
示例
func test(i interface{}) { n, ok := i.(int) if !ok { return } n += 10 } func main() { var t1 int test(t1) }
reflect
reflect.Value.NumField(),获取结构体中字段的个数
reflect.Value.Method(n).Call(nil),调用结构体中的方法
reflect.TypeOf,返回一个Type类型值
reflect.Value.Kind,返回一个常量,表示变量的类别
reflect.ValueOf,返回一个Value类型值,该值代表运行时的数据
SetXX(x) 因为传递的是x的副本,所以SetXX不能够改x,要改动x必须向函数传递x的指针
//> SetInt、SetFloat、SetString //错误代码!!! //panic: reflect: reflect.Value.SetFloat using unaddressable value func main() { var a float64 fv := reflect.ValueOf(&a) fv.SetFloat(520.00) } //正确的,传指针 func main() { var a2 float64 fv2 := reflect.ValueOf(&a2) fv2.Elem().SetFloat(520.00) fmt.Printf("%v\n", a2) //520 }
goroutine
recover()
channel
chonlyread := make(<-chan int) //创建只读channel
chonlywrite := make(chan<- int) //创建只写channel
Last updated
Was this helpful?