golang 知识点.总结一

golang 知识点总结

此系列文档根据慕课网 golang视频总结的个模块知识点汇总。

1.1 变量定义

1.1.1 使用 var 关键字

  • var a, b, c bool
  • var s1, s2 string = “hello”, “world”
  • 可放在函数内,或直接放在包内
  • 使用 var() 集中定义变量

1.1.2 让编译器自动决定类型

  • var a, b, i, s1, s2 = true, false, 3, “hello”, “world”

1.1.3 使用 := 定义变量(只能在函数内部)

  • a, b, i, s1, s2 := true, false, 3, “hello”, “world”

1.2 内建变量类型

  • bool, string
  • (u)int, (u)int8, (u)int16, (u)int32, (u)int64, uintptr
  • byte, rune
  • float32, float4, complex64, complex128

1.2.1 强制类型转换

  • 类型转换是强制的
  • var a, b int =3 ,4
  • var c int = math.Sqrt(a * a + b * b) X错误写法
  • var c int = int(math.Sqrt(float63(a * a + b * b)) √ 正确写法
  • ? 如果算出来是4.999 => int出来是变成 4
package main

import (
    "math"
    "fmt"
)

func triangle() {
    var a, b int = 3, 4
    var c int

    // 这里 go 不能隐式的转换类型,所以要在显示转换加入int()
    c = int(math.Sqrt(float64(a*a + b*b)))
    fmt.Println(c)
}

func main() {
    triangle()
}
// => 5

变量定义要点回顾

  • 变量类型写在变量名之后
  • 编译器可推测变量类型
  • 没有 char 只有 rune
  • 原生支持复数类型 complex

1.3 常亮与枚举

1.3.1 常量

  • const filename = “abc.txt”
  • const 数值可作为各种类型使用(不用转换)
  • const a, b =3, 5
  • var c int = int(math.Sqrt(a * a + b * b)) 这里就不用将a ,b 转化为float64.

1.3.2 枚举类型的常量

  • 普通枚举类型

  • 自增值枚举类型

/*
 *  枚举类型的常量
 */
func enums() {
    const (
        cpp = iota
        _  // 这里的 _ 表示不用次常量,但要占位置。
        python
        golang
        javascript
    )

    // b , kb, mb, gb, tb ,pb
    const (
        b = 1 << (10 * iota)  // 二进制为1 左移 多少位
        kb
        mb
        gb
        tb
        pb

    )

    fmt.Println(cpp, javascript, python, golang)
    // => 0 4 2 3
    fmt.Println(b , kb, mb, gb, tb ,pb)
}

1.4 条件语句

1.4.1 if 条件判断

package main

import(
    "fmt"
    "io/ioutil"
)
func main(){
    const filename = "abc.txt"
    if contents, err := ioutil.ReadFile(filename); err != nil {
        fmt.Println(err)
    } else {
        // fmt.Println(contents)
        fmt.Printf("%s\n", contents)
    }

    fmt.Println(consts) // => undefined: consts
}
  • if 的条件里可以赋值
  • if 的条件里赋值的变量作用域只能在这个 if 语句里

1.4.2 switch 条件判断

  • switch 会自动break,除非你不break 则用 fallthrough
  • switch 后可以没有表达式
func eval(a, b int, op string) int {
    var result int
    switch op {
    case "+":
        result = a + b
    case "-":
        result = a - b
    case "*":
        result = a * b
    case "/":
        result = a / b
    default:
        panic("unsupported operator:" + op)
    }
    return result
}

func grade(score int) string {
    g := ""
    switch {
    case score < 0 || score > 100:
        panic(fmt.Sprintf(
            "Wrong scor: %d", score))
    case score < 60:
        g = "F"
    case score < 80:
        g = "C"
    case score < 90:
        g = "B"
    case score <= 100:
        g = "A"
    }
    return g
}
func main() {
    fmt.Println(
        grade(0),   // F
        grade(59),  // F
        grade(60),  // C
        grade(82),  // B
        grade(99),  // A
        grade(100), // A
        // grade(101),
        // grade(-3),
    )

    fmt.Println(
        eval(10, 90, "+"), // 100
        eval(5, 10, "-"),  // 5
    )
}

1.5 循环

  • for 的条件里不需要括号
  • for 的条件里可以省略初试条件,结束条件,递增表达式
// printFile("abc.txt")
func printFile(filename string) {
    file, err := os.Open(filename) 
    if err != nil {
        panic(err)
    }
    scanner := bufio.NewScanner(file)

    for scanner.Scan() {
        fmt.Println(scanner.Text()) 
        /* => aaaa
            golang no.1
            javascript
            node.js
        */
        
    }
    
}

func forever() {
    // go 语言的死循环
    for {
        fmt.Println("abc")
    }
}
  • 省略初试条件,相当于while
  • 全部省略,死循环

1.6 函数

  • 函数可返回多个值
  • 函数返回多个值时可以起名字(不要乱用,仅用于非常简单的函数, 对于调用者而言没有区别)
  • 可变参数列表(没有默认参数,可选参数)
package main

import (
    "math"
    "runtime"
    "reflect"
    "fmt"
)

func eval(a, b int, op string) (int, error) {
 
    switch op {
    case "+":
        return a + b, nil
    case "-":
        return a - b, nil
    case "*":
        return a * b, nil
    case "/":
        q, _ := div(a, b) // 这里用不到返回值r,如果加上会报错,因为没有用到
        return q, nil
    default:
        return 0, fmt.Errorf("unsupported operation: %s", op)
    }
}


// 可返回多值
func div(a, b int) (q, r int) {
    return a / b, a % b
}

func apply(op func(int, int) int, a, b int) int {
    p := reflect.ValueOf(op).Pointer()    // 反射,拿到函数的指针
    opName := runtime.FuncForPC(p).Name() // 为了拿到传入的函数名称
    fmt.Printf("Calling function %s with args " + "(%d, %d)\n",
     opName, a, b)

     return op(a, b)
}

// 可变参数列表
func sum(numbers ...int) int {
    s := 0
    for i := range numbers {
        s += numbers[i]
    }
    
    return s
}

// func Pow(a, b int) int {
//  return int(math.Pow(float64(a), float64(b)))
// }

func main() {
    fmt.Println(eval(3, 4, "*")) 

    if result, err := eval(3, 4, "x"); err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println(result)
    }

    q, r := div(13, 3)
    fmt.Println(q, r)

    fmt.Println(apply(  // 函数式编程
        func (a, b int) int {
            return int(math.Pow(float64(a), float64(b)))
        },3, 4))
    
    fmt.Println(sum(1, 2, 3))

}

1.7 ++指针++(重要)

go 语音的指针比较 C 语音更为简单:

  • 指针不能运算

1.7.1 参数传递

许多语言如: Java Python JavaScript 都是引用传递参数(就是直接调用自身底层数据,它会改变) - go 语言只有 值传递一种方式(调用的是复制的值,不会改变底层数据,除非用指针)

// 指针
func swap(a, b *int) {
    *b, *a = *a, *b
}

a, b := 3, 4
    swap(&a, &b)
    fmt.Println(a, b) // => 4, 3
Go  基础