每一个源文件都可以包含一个init函数,init会在main函数前被调用. 全局变量定义-->init函数-->main函数
方式1. 只能使用一次 res := func (n1 int) int { return n1+n1 } (10) 方式2. 可以多次使用 a := func (n1 int) int { return n1+n1 } a(10) 如果将匿名函数赋给一个全局变量,那么这个匿名函数就是全局匿名函数
func Test() func (int) int{ var n int = 10 return func (x int) int { n = n + x return n } } 调用: 每调用一次 f() 里面的值将进行累加 f := Test() fmt.println(f(2))
当执行到defer时, 暂不执行压入到独立的栈,当函数执行完后再执行, 出栈(先入后出 ) 如果涉及到变量, 则会将变量拷贝一份进栈, 当前函数变量的值修改后不会对栈内的值造成影响
两种传递方式: 不管是值传递还是引用传递都是传递变量的拷贝,引用传递效率高,值传递取决于值的大小 如果希望函数内的变量能修改函数外的变量,可以传入变量的地址 &, 函数内以指针的方式操作变量
基本数据类型 int float bool string 数组 结构体struct
指针 slice切片 map 管道chan interface等都是引用类型
函数内声明/定义的变量叫局部变量,作用域仅函数内部 函数外声明/定义的变量叫全局变量,作用域整个包都有效,如果首字母为大写则整个程序都有效 变量是在一个代码块中 for if ,则只作用域仅该代码块
go统一为utf-8, len统计汉字占3
r := []rune(str)
n, err := strconv.Atoi("12")
n, err := strconv.Itoa(123456)
b := []byte("hello")
str := string([]byte{97,98,99})
a := strconv.FormatInt(123, 2) // 结果类型是字符串
strings.Contains("chinese", "es") // true
strings.Count("chinese", "es") //1
strings.EqualFold
strings.Index("chinese", "es") // 首次出现 如果没有返回 -1 strings.LastIndex("chinese", "es") // 最后一次出现 如果没有返回 -1
strings.Replace("abcabc", "a", "b", -1) // 数据, 查找目标, 替换成, 替换次数 -1为全部
strings.Split("aaaa,ddd", ",")
strings.ToLower strings.TuUpper
strings.TrimSpace(str) 头尾去空格 strings.Trim(str, "char") 头尾去掉指定字符 strings.TrimLeft(str, "char") 左边去掉指定字符 strings.TrimRight(str, "char") 右边去掉指定字符
strings.HasPrefix(str, "char") //以字符开头 strings.HasSuffix(str, "char") // 以字符结尾
now := time.Now() now.Year() //等 fmt.Printf或者fmt.Sprintf 格式化时间 now.Format(时间格式) time.Sleep(time.Second * 2) now.Unix()时间戳
分配内存 分配值类型 如 int struct float32 返回的是指针
分配内存, 分配引用类型,比如 channel map slice
go不支持传统的try, 引入了defer panic recover 使用场景: 抛出一个panic异常, 然后通过defer + recover捕获处理 func test() { defer func() { err := recover() if err != nil { fmt.Println(err) } } res := 10 / 0 fmt.Println(res) }
errors.New("错误说明") panic内置函数 接收一个interface{}类型的值作为参数, 可以接收error类型的变量,输出错误信息并退出程序 //返回一个error类型的值, 表示一个错误 func readConf(name string) (err error) { if name == "config.ini" { //读取... return nil } else { //返回一个自定义错误 return errors.New("读取文件错误..") } } err := readConf("config2.ini") if err != nil { //如果读取文件发送错误,就输出这个错误,并终止程序 panic(err) }
数组是值类型,只能存放相同的一种数据 数组一旦声明定义了,其长度是固定的 数组的元素可以是任何数据类型, 但必须是同一种,不能混用 数组创建后如果没有赋值, 默认是零值 下标是0开始,有越界的异常,作为参数传递是默认是值拷贝 在其它函数中想去修改数组的值,可以使用引用传递(指针)
方法一 var str [2]string str[0] = "world" str[1] = "hello" fmt.Println(str) 方法二 str1 := [2]string{"12", "safas"} var str1 [2]string = [2]string{"12", "safas"} var data [10]int data = [10]int{1, 2, 3, 4, 5} 方法三 [...]是规定写法 var str1 = [...]string{"12", "safas"} 方法四 var str1 = [...]string{1: "12", 0: "safas"} str1 := [...]string{1: "12", 0: "safas"}
&数组名就是地址, 第一个元素的地址也是数组的首地址,各元素地址间隔是依据数组的类型决定
用下标访问 常规for遍历 for--range遍历 for index,val := range array01 { ... }
传递指针
arr := [3]int{11, 22, 33}
//函数1 func test01(arr [3]int) { arr[0] = 88 } test01(arr) //函数1不会改变原数组的值 //函数2 func test02(arr *[3]int) { fmt.Printf("arr指针的地址=%p", &arr) (*arr)[0] = 88 //!! } test02(&arr) //函数2 改变原数组的值