美文网首页
Go语言基础

Go语言基础

作者: 贝壳的世界 | 来源:发表于2022-10-03 09:25 被阅读0次

    程序结构

    变量

    • 标准语法:var 变量名字 类型 = 表达式 var i int = 1
    • 简短语法:变量名字 := 表达式 j := 2

    常量

    • 关键字:const
    • 语法:const 常量名 = 编译期确定的值
    • 常量值:字符、字符串、布尔值、数值。
    • 常量不能用 := 语法声明

    类型

    • 语法:type 类型名字 底层类型
    type Person struct {
        name string
        age int
    }
    

    控制语句

    for

    Go中唯一的循环结构

    sum := 0
    for i := 0; i < 10; i++ {
      sum += i
    }
    

    if-else

    func sqrt(x float64) string {
        if x < 0 {
                return sqrt(-x) + "i"
        }
          return fmt.Sprint(math.Sqrt(x))
    }
    
    • 特点:可以在条件表达式前执行一个简单的语句
    func pow(x, n, lim float64) float64 {
          if v := math.Pow(x, n); v < lim {
              return v
          }
          return lim
    }
    

    switch-case

    • 只执行匹配的case(Go自动加了break语句)
    • case 无需为常量,且取值不必为整数
        switch os := runtime.GOOS; os {
        case "darwin":
            fmt.Println("OS X.")
        case "linux":
            fmt.Println("Linux.")
        default:
            // freebsd, openbsd,
            // plan9, windows...
            fmt.Printf("%s.\n", os)
        }
    

    defer

    • defer 语句会将函数推迟到外层函数返回之后执行。
    • 推迟的函数调用会被压入一个栈中,按照后进先出的顺序调用。
    defer fmt.Println("world")
    fmt.Println("hello")
    

    包和文件

    • 文件:组织Go代码
    • 包:管理Go文件,支持模块化,独立命名空间
    • 导出规则:如果一个名字是大写字母开头的,那么该名字是导出的,包外可访问
    • 匿名导入:它会计算包级变量的初始化表达式和执行导入包的init初始化函数

    基础数据类型

    整型

    • 有符号整数:int8、int16、int32、int64、int、rune
    • 无符号整数:uint8、uint16、uint32、uint64、uint、uintptr、byte
    • int、uint、uintptr:在32位系统上是32位,在64位系统上是64位
    • byte:等同于uint8,表示一个字节
    • rune:等同于int32,表示一个Unicode码点

    浮点型

    • 浮点数:float32、float64
    • 复数:complex64、complex128

    布尔型

    bool:true、false

    字符串

    • string:默认使用UTF8编码
    • 常用包:bytes、strings、strconv、unicode

    零值

    声明但未初始化的变量会被赋予零值

    • 数值类型:0
    • 布尔类型:false
    • 字符串:""
    var i int
    var b bool
    var s string
    fmt.Printf("%v %v %q\n", i, b, s) // 0 false ""
    

    类型转换

    表达式 T(v) 将值 v 转换为类型 T

    i := 42
    f := float64(i)
    u := uint(f)
    

    复合数据类型

    数组

    • 声明:var a [3]int
    • 初始化:var q [3]int = [3]int{1, 2, 3}
    • 简短写法:a := [3]int{1, 2, 3}

    切片

    • 声明:var s []int
    • 添加元素:s = append(s, 1, 2, 3)
    • 切片操作:s[i:j],表示s的从第i个元素开始到第j-1个元素的子序列。
    • 切片的长度:它所包含的元素个数,len(s)
    • 切片的容量:从它的第一个元素开始数,到其底层数组元素末尾的个数,cap(s)
    • 切片的零值:nil

    哈希表

    • 创建
    // m1 = nil
    m1 := make(map[string]int)
    
    // m2 = {}
    m2 := map[string]int{}
    
    // m3 = {"age":18}
    m2 := map[string]int{
      "age": 18,
    }
    
    • 读写
    m[key] = elem // 新增或更新
    elem = m[key] // 获取
    delete(m, key) // 删除
    elem, ok := m[key] // 判断键是否存在
    

    结构体

    • 定义
    type Employee struct {
        ID        int
        Name      string
    }
    
    • 初始化
    e := Employee{
      ID: 123,
      Name: "test",
    }
    
    • JSON序列化
    type Employee struct {
        ID        int `json:"id"`
        Name      string `json:"name"`
    }
    
    data, err := json.Marshal(e)
    if err != nil {
        log.Fatalf("JSON marshaling failed: %v", err)
    }
    fmt.Printf("%s\n", data)
    

    range

    // 遍历数组
    for index, value := range array {
        fmt.Printf("%d %d\n", index, value)
    }
    
    // 忽略index
    for _, value := range array {
        fmt.Printf("%d\n", value)
    }
    
    // 忽略value
    for index := range array {
        fmt.Printf("%d\n", index)
    }
    
    // 遍历哈希表
    for key, value := range map {
        fmt.Printf("%d %d\n", key, value)
    }
    

    函数

    声明

    func name(parameter-list) (result-list) {
        body
    }
    
    func add(x int, y int) int {
          return x + y
    }
    
    // 如果连续参数类型相同,可以简写为:
    func add(x, y int) int {
          return x + y
    }
    

    多返回值

    在Go中,函数可以返回任意数量的返回值。

    func swap(x, y string) (string, string) {
        return y, x
    }
    

    方法

    声明

    方法就是一类带特殊的接收者参数的函数。

    // 方式1:值类型
    func (t T) name(parameter-list) (result-list) {
        body
    }
    
    // 方式2:指针类型
    func (t *T) name(parameter-list) (result-list) {
        body
    }
    

    方式1和方式2的区别:调用方法时,前者是深拷贝,后者是浅拷贝。

    封装

    type Counter struct { n int }
    func (c *Counter) N() int     { return c.n }
    func (c *Counter) Increment() { c.n++ }
    func (c *Counter) Reset()     { c.n = 0 }
    

    接口

    声明

    type error interface {
        Error() string
    }
    

    实现

    隐式实现:一个类型拥有某接口的所有方法,则该类型就实现了这个接口。

    // errorString类型
    type errorString struct { 
        text string
    }
    
    // 实现error接口
    func (e *errorString) Error() string {
        return e.text 
    }
    

    使用

    func New(text string) error { 
        return &errorString{text}
    }
    

    空接口

    • 形式:interface{}
    • 空接口可保存任何类型的值。
    • 空接口被用来处理未知类型的值。
    func describe(i interface{}) {
          fmt.Printf("(%v, %T)\n", i, i)
    }
    
    func main() {
          var i interface{}
          describe(i) // (<nil>, <nil>)
    
          i = 42
          describe(i) // (42, int)
    
          i = "hello"
          describe(i) // (hello, string)
    }
    

    类型断言

    • 类型断言:提供了访问接口值底层具体值的方式。
    • t := i.(T):断言接口值 i 保存了具体类型 T,并将其底层类型为 T 的值赋予变量 t。若 i 并未保存 T 类型的值,则会触发panic异常。
    • t, ok := i.(T) 判断接口值 i 是否保存了具体类型 T,如果为true,那么 t 将会是其底层值,否则而 t 将为 T 类型的零值。不会触发panic异常。

    类型选择

    • 类型选择:一种按顺序从几个类型断言中选择分支的结构。
    switch v := i.(type) {
    case T:
        // v 的类型为 T
    case S:
        // v 的类型为 S
    default:
        // 没有匹配,v 与 i 的类型相同
    }
    

    本文由mdnice多平台发布

    相关文章

      网友评论

          本文标题:Go语言基础

          本文链接:https://www.haomeiwen.com/subject/yseyartx.html