go基础2

117 阅读5分钟

函数

defer

defer延迟机制,可以让资源快速释放 在函数中defer语句,将会在函数执行完后,立即执行 如果一个函数里有多个defer函数,那么defer语句会按照书写的逆序进行

// 语法
func 函数名(params paramsType) (returnVal returnType) {
  defer ...

  ...
}
// 例子
package main

import "fmt"

func sum(n1, n2 int) int {
  defer fmt.Println("这是defer")
  result := n1 + n2
  fmt.Println("result:", result)
}

func main() {
  sum(10, 20)
}

/**
 输出结果:
 result:30
 这是defer
*/

一般使用 defer 语句来延迟执行关闭打开的进程或文件

// 例子
package main

import (
	"fmt"
	"net"
	"os"
)

func main() {
	listen, err := net.Listen("tcp", "127.0.0.1:3000")
	if err != nil {
		fmt.Println("listen err:", err)
		os.Exit(1) // 结束当前进程
	}
  // 关闭listen
	defer listen.Close()
}

注意:当 defer 和 return 遇上时,defer 会在 return 后执行

函数错误处理

判断函数是成功还是失败,可以在返回参数中加一个error参数,如果error有值则发生错误,否则函数调用成功

// 语法
func funcName(params paramsType) (returnVal returnType, err error) {
  ...
}
// 例子
package main

import (
    "fmt"
    "net"
    "os"
)
// 还是这个例子 net.Listen函数 就有两个返回值

/**
net.Listen方法源代码

func Listen(network, address string) (Listener, error) {
    var lc ListenConfig
    return lc.Listen(context.Background(), network, address)
}
*/

func main() {
    listen, err := net.Listen("tcp", "127.0.0.1:3000")
    if err != nil {
        fmt.Println("listen err:", err)
        os.Exit(1) // 结束当前进程
    }
    // 关闭listen
    defer listen.Close()

}

panic 和 recover

如果函数或程序出现严重问题,不该往下执行下去,就该终止,处理这种致命的错误一般就是通过 panic 方法

// 语法
func funcName(params paramsType) (returnVals returnType) {
  if (condition) {
    panic("Error Info")
  }
}
// 例子
package main

import "fmt"

func div(n1, n2 int) int {
  if n2 == 0 {
    panic("除数为 0") 
  }
  return n1/n2
}

func main() {
  result := div(2, 0)
  fmt.Println("结果是:", result)
}

但是我们要想在出现 panic 后,还能继续向下执行,并将 panic 错误打印出来,这就用到我们的 recover

// 语法   recover 一般与 defer 一起使用
defer func() {
    if r := recover(); r != nil {
        fmt.Println("Recovered in f", r)
    }
}()
// 例子
package main

import "fmt"

func div(n1, n2 int) int {
    if n2 == 0 {
        panic("除数为 0")
    }
    return n1 / n2
}

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("异常报错为:", r)
        }
    }()
    fmt.Println("开始程序")
    div(2, 0)
    fmt.Println("程序正常结束")
}
/**
输出结果:
开始程序
异常报错为: 除数为 0
*/

字符串(String)

注意字符串在go里只能用双引号,单引号是字符,两者不相同

String 的一些常用方法

截取字符串
// 语法
string[start : end]
参数描述
string源字符串
start开始截取的下标,不指定默认为0
end结束截取的下标,不指定默认为字符串长度
// 例子
package main

import "fmt"

func main() {
  str := "Hello every body"
  fmt.Println(str[1:5])
  fmt.Println(str[5:])
  fmt.Println(str[:10])
  /**
    输出结果:
    ello
     every body
    Hello ever
  */
}
拼接字符串
  • 使用 + 号
  • 使用join函数拼接
  • 使用buffer.WriteString函数拼接
  • 使用buffer.Builder拼接
// 例子
package main

import (
  "bytes"
  "fmt"
  "strings"
)

func main() {
    str1 := "join"
    str2 := " me"

    // 使用 + 号
    str3 := str1 + str2

    // 使用 join 函数拼接 -- 类似于 JS 里的 join 函数
    strSlice := []string{str1, str2}
    str4 := strings.Join(strSlice, "")

    // 使用buffer.WriteString函数拼接 -- 注意 Buffer 默认容量是64
    var bt bytes.Buffer
    bt.WriteString(str1)
    bt.WriteString(str2)
    str5 := bt.String()

    // 使用buffer.Builder拼接
    var build strings.Builder
    build.WriteString(str1)
    build.WriteString(str2)
    str6 := build.String()

    fmt.Printf("%s\n%s\n%s\n%s\n", str3, str4, str5, str6)
}
获取字符串
// 语法
len([]rune(str))
获取子串长度
// 语法
strings.Count(str, substr)
参数描述
str要获取长度的字符串
substr子串
// 例子
package main

import (
    "fmt"
    "strings"
)

func main() {
    str := "world is ours"
    fmt.Println("s count is ", strings.Count(str, "s"))
    fmt.Println("str len is ", len(str))
}
/**
输出结果:
s count is  2
str len is  13
*/
分割字符串
// 语法

arr := strings.Split(str,sep)
参数描述
str要分割的字符串
sep分割符
// 例子
package main

import (
    "fmt"
    "strings"
)

func main() {
    str := "we are the world"
    arr := strings.Split(str, " ")
    fmt.Println(arr)
  /**
  输出结果:
  [we are the world]
  */
}

切片

因为go中的数组的长度是固定的,不可更改的,所以集合类的我们一般使用切片来代替数组的使用

创建切片

 // 语法
 // 这一方式创建与创建数组的区别就是没有设定元素ele的数量
 varName := []type{ele1, ele2, ...}

/**
  make方式
  type 切片元素类型
  len 切片的长度
  cap 切片的容量
*/
 varName := make([]type, len, [cap])

 // 由数组截取创建切片的方式就不列了

1、切片容量默认是切片的长度
2、当切片的长度大于切片的容量时,切片的容量会以双倍的形式自动扩容

// 例子
package main

import "fmt"

func main() {
  slice1 := []int{ 1, 2, 3, 4 }
  slice2 := make([]int, 3, 4)

  fmt.Printf("slice1 is %v , len is %v, cap is %v\n", slice1, len(slice1), cap(slice1))
  fmt.Printf("slice2 is %v , len is %v, cap is %v\n", slice2, len(slice2), cap(slice2))
}
/**
输出结果:
slice1 is [1 2 3 4] , len is 4, cap is 4
slice2 is [0 0 0] , len is 3, cap is 4
*/
append

append为切片增加元素,返回一个新的切片

// 语法
append(slice []Type, elems ...Type) []Type

slice = append(slice, elem1, elem2)
// 也可以组合切片 注意后面要加三个点
slice = append(slice, anotherSlice...)
参数描述
slice需要添加的切片
elems跟切片元素同类型的数据
// 例子
package main

import "fmt"

func main() {
  slice := []int{1, 2, 3, 4}
  fmt.Println("slice:", slice)
  // append 返回一个新的切片
  slice1 := append(slice, 5, 6, 7)
  fmt.Println("slice after append:", slice)
}

go 并没有提供用于删除元素的语法或接口,切片怎么删除元素呢,可以利用append可以组合slice的特性

// 例子
package main

import "fmt"

func main() {
  slice := []string{"a", "b", "c", "d", "e"}
  // 删除b,c
  newSlice := append(slice[:1], slice[2:]...)

  fmt.Println("newSlice:", newSlice)
}
/**
输出结果:
newSlice: [a d e]
*/

Map

创建map

// 语法
var mapName map[keyType]valueType
// make方法创建
var mapName = make(map[keyType]valueType, len)
// 例子
package main

import "fmt"

func main() {
  // 注意最后一行也要加逗号
  HotelMap := map[string]string{
    "hanting": "汉庭酒店",
    "juzi":    "桔子酒店",
    "quanji":  "全季酒店",
  }
  fmt.Println("HotelMap:", HotelMap)
  // 循环遍历
  for k, v := range HotelMap {
		fmt.Println("key:", k, "value:", v)
	}
}
/**
输出结果:
HotelMap: map[hanting:汉庭酒店 juzi:桔子酒店 quanji:全季酒店]
key: quanji value: 全季酒店
key: hanting value: 汉庭酒店
key: juzi value: 桔子酒店
*/

判断从map是否能渠道值

// 例子
package main

import "fmt"

func main() {
  // 注意最后一行也要加逗号
  HotelMap := map[string]string{
    "hanting": "汉庭酒店",
    "juzi":    "桔子酒店",
    "quanji":  "全季酒店",
  }
  fmt.Println("HotelMap:", HotelMap)
  if hotel, isOk := HotelMap["juzi"]; isOk {
    fmt.Println("hotel:", hotel)
  }
}

删除map中的元素

// 语法
delete(mapName, KEY)
参数描述
mapName要删除的 map
KEY要删除的键
package main

import "fmt"

func main() {
  // 注意最后一行也要加逗号
  HotelMap := map[string]string{
    "hanting": "汉庭酒店",
    "juzi":    "桔子酒店",
    "quanji":  "全季酒店",
  }
  delete(HotelMap, "quanji")
  fmt.Println("HotelMap:", HotelMap)
}
/**
输出结果:
HotelMap: map[hanting:汉庭酒店 juzi:桔子酒店]
*/